diff --git a/.hgtags b/.hgtags
index 8cb9dfcce9..2f478ffdf4 100644
--- a/.hgtags
+++ b/.hgtags
@@ -19,3 +19,3000 @@ beafebc0035e2da56414691f6101a04e2edb8c5c sale_amendment-6.2.0
be0373f2c571c7abe516b6731be295ee1a58d046 sale_amendment-6.4.0
0000000000000000000000000000000000000000 6.6.0
0ac4d1dee92a2d241ed3f4644d363288fa163fc1 sale_amendment-6.6.0
+c519bba52eaea7cd951380a64c62256f6bee7835 6.6.0
+0000000000000000000000000000000000000000 6.6.0
+c519bba52eaea7cd951380a64c62256f6bee7835 sale_blanket_agreement-6.6.0
+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
+04832390b9f8b27fde64024764b61515435c5f31 6.2.0
+b0ceb357f0f05712ec08b62be561e9d4c97fe2b1 6.4.0
+bd637b711ec782a7f0604a4dc073937630afc4ef 6.6.0
+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.2.0
+04832390b9f8b27fde64024764b61515435c5f31 sale_complaint-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+b0ceb357f0f05712ec08b62be561e9d4c97fe2b1 sale_complaint-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+bd637b711ec782a7f0604a4dc073937630afc4ef sale_complaint-6.6.0
+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
+96805268ecec102422312d4dcb66e51dc72f7ee3 6.2.0
+ccd0735b90fe580dfe719273d80f448dd05359af 6.4.0
+9f545c6ac69864520310f5e8d117e83a9b8e6b81 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+96805268ecec102422312d4dcb66e51dc72f7ee3 sale_credit_limit-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+ccd0735b90fe580dfe719273d80f448dd05359af sale_credit_limit-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+9f545c6ac69864520310f5e8d117e83a9b8e6b81 sale_credit_limit-6.6.0
+048f3939e4fe68df605f29805d421f0e4029e1e3 5.8.0
+e11442b5963bc719317414861dd81c13c7b941ce 6.0.0
+7799a1ee14e380bf2b1fb3dbf20136af200c5d4b 6.2.0
+4af6d96d6d6297747215c963869820830853c055 6.4.0
+29b63d4e5b9c22a6ef2ae42f3d2afdbd07a855c9 6.6.0
+0000000000000000000000000000000000000000 5.8.0
+048f3939e4fe68df605f29805d421f0e4029e1e3 sale_discount-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+e11442b5963bc719317414861dd81c13c7b941ce sale_discount-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+7799a1ee14e380bf2b1fb3dbf20136af200c5d4b sale_discount-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+4af6d96d6d6297747215c963869820830853c055 sale_discount-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+29b63d4e5b9c22a6ef2ae42f3d2afdbd07a855c9 sale_discount-6.6.0
+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
+4db8c1cac42da1712c7ea2af1cf35e15ee4f73e0 6.2.0
+26378efb268e690f89e286eeb4277d95b1cf4eeb 6.4.0
+81cff3b0a1683ef1511877fb601ed49025854cff 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+4db8c1cac42da1712c7ea2af1cf35e15ee4f73e0 sale_extra-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+26378efb268e690f89e286eeb4277d95b1cf4eeb sale_extra-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+81cff3b0a1683ef1511877fb601ed49025854cff sale_extra-6.6.0
+f7260dcf0ebb5739b6b66482ba4bc09b0d4f3e1d 6.0.0
+dd4ffec95eb69e1bb824fe45ae9aedcb0ad953c5 6.2.0
+db637b28c5f6b1686bb17144037ff9b832e918a6 6.4.0
+17856e04e107f10550e0230221f6efed50e6cf4a 6.6.0
+0000000000000000000000000000000000000000 6.0.0
+f7260dcf0ebb5739b6b66482ba4bc09b0d4f3e1d sale_gift_card-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+dd4ffec95eb69e1bb824fe45ae9aedcb0ad953c5 sale_gift_card-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+db637b28c5f6b1686bb17144037ff9b832e918a6 sale_gift_card-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+17856e04e107f10550e0230221f6efed50e6cf4a sale_gift_card-6.6.0
+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
+22fa5ffe0af4ef4a073253c71483e97dc2fb26de 6.2.0
+baafc12549df591558de8bf2718866a8fcfaf203 6.4.0
+4d9368f4116eb30ed111789e868af184c78fd1b1 6.6.0
+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.2.0
+22fa5ffe0af4ef4a073253c71483e97dc2fb26de sale-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+baafc12549df591558de8bf2718866a8fcfaf203 sale-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+4d9368f4116eb30ed111789e868af184c78fd1b1 sale-6.6.0
+183c2adb200e9ebb4d04e37d16843a86842e5fc4 5.4.0
+818c4a409fd405f8e29257235d3f33c228f98528 5.6.0
+037afc127047ce9a8558cb7f3c5778b8ff84eb60 5.8.0
+18ef01aa2e6feb211bbfc1a53449e227f369ffee 6.0.0
+d8dc0cfe490442a6efaab0dc888c1bf7e0d048a2 6.2.0
+0a4dd0908559298697c0be7494424775a9c707d7 6.4.0
+6f4a6c055f149f80b82f89debe1c72d63e5a4176 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+d8dc0cfe490442a6efaab0dc888c1bf7e0d048a2 sale_history-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+0a4dd0908559298697c0be7494424775a9c707d7 sale_history-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+6f4a6c055f149f80b82f89debe1c72d63e5a4176 sale_history-6.6.0
+a4ef33c3033b6924ad5e562467e3baa8f2858764 6.4.0
+365fb9386bcd4955e4a20faf7d5a05a0d285033d 6.6.0
+0000000000000000000000000000000000000000 6.4.0
+a4ef33c3033b6924ad5e562467e3baa8f2858764 sale_invoice_date-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+365fb9386bcd4955e4a20faf7d5a05a0d285033d sale_invoice_date-6.6.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
+677012ee69b8dced3cd9391374943994d3c12048 6.2.0
+2ac37bcedb1c37c0568f1f2a3f47a685edec81f1 6.4.0
+bd44515334a9e4ce95ad522c458e3aace18ec23f 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+677012ee69b8dced3cd9391374943994d3c12048 sale_invoice_grouping-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+2ac37bcedb1c37c0568f1f2a3f47a685edec81f1 sale_invoice_grouping-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+bd44515334a9e4ce95ad522c458e3aace18ec23f sale_invoice_grouping-6.6.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
+22d88d156c58928f28d8f55fecbb68946c920013 6.2.0
+97c8522c683247b4165447eb731f29ed52abb803 6.4.0
+947542b39dec6dcb83fe47a0f82ac944d7ed2e03 6.6.0
+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.2.0
+22d88d156c58928f28d8f55fecbb68946c920013 sale_opportunity-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+97c8522c683247b4165447eb731f29ed52abb803 sale_opportunity-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+947542b39dec6dcb83fe47a0f82ac944d7ed2e03 sale_opportunity-6.6.0
+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
+cab63268fbe953836764bf4aa7fde13196c6731d 6.2.0
+62a4a9b4bc573dad815d6edd636d64a82c9ae1e8 6.4.0
+5acfeb4d037de105e2cb054d448eccb96f544d17 6.6.0
+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.2.0
+cab63268fbe953836764bf4aa7fde13196c6731d sale_payment-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+62a4a9b4bc573dad815d6edd636d64a82c9ae1e8 sale_payment-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+5acfeb4d037de105e2cb054d448eccb96f544d17 sale_payment-6.6.0
+abd6906e773b306d37ff7abba63d22c1f8ba6f48 6.2.0
+617725de9f668fbab96e8fba386b94a62c4b8a85 6.4.0
+ca2bb8e062fbb53e1f4dbaef01d6afc626b79e3a 6.6.0
+0000000000000000000000000000000000000000 6.2.0
+abd6906e773b306d37ff7abba63d22c1f8ba6f48 sale_point-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+617725de9f668fbab96e8fba386b94a62c4b8a85 sale_point-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+ca2bb8e062fbb53e1f4dbaef01d6afc626b79e3a sale_point-6.6.0
+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
+cb1596e6054372c0e5461e7ad59452449d8d5806 6.2.0
+7570623adac49129c580b5d89d035a0b75e854a7 6.4.0
+76127b48d2faf3870bddfc9109a55a23ddc8eaf3 6.6.0
+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.2.0
+cb1596e6054372c0e5461e7ad59452449d8d5806 sale_price_list-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+7570623adac49129c580b5d89d035a0b75e854a7 sale_price_list-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+76127b48d2faf3870bddfc9109a55a23ddc8eaf3 sale_price_list-6.6.0
+3bc89a03c30827599ba2358137451740c0ed3d32 5.2.0
+8601dafabd0098f2e5df235458ee3d3cd9a7c56d 5.4.0
+e55081ceaa04185643d06774bf80303827e4d53b 5.6.0
+875d7e3c1ea4f922723e9e513171f86d4e47ce06 5.8.0
+8fbeddc61c5fbf7fcd6ea98ca8c918030035c435 6.0.0
+fcdea2dcd7dc001e55bf1a1550640f3b16a5e4ad 6.2.0
+a3d38c539e95706189bf10573527d29363a0f790 6.4.0
+bd52627bd93eb9c25bfbcfad76fe5f30ff27c8d9 6.6.0
+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.2.0
+fcdea2dcd7dc001e55bf1a1550640f3b16a5e4ad sale_product_customer-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+a3d38c539e95706189bf10573527d29363a0f790 sale_product_customer-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+bd52627bd93eb9c25bfbcfad76fe5f30ff27c8d9 sale_product_customer-6.6.0
+88c997797006966aea5d7368fe5e9a35bc286a60 6.4.0
+6403d2eb3b8f3fe6dd4da113cdcb5453e5f34b76 6.6.0
+0000000000000000000000000000000000000000 6.4.0
+88c997797006966aea5d7368fe5e9a35bc286a60 sale_product_quantity-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+6403d2eb3b8f3fe6dd4da113cdcb5453e5f34b76 sale_product_quantity-6.6.0
+eed5e95d5ad28ea88dd9d58506111ae2acabc733 6.6.0
+0000000000000000000000000000000000000000 6.6.0
+eed5e95d5ad28ea88dd9d58506111ae2acabc733 sale_product_recommendation_association_rule-6.6.0
+fac68f8d1c61a715eb6bfa654c2a64736d42d2be 6.6.0
+0000000000000000000000000000000000000000 6.6.0
+fac68f8d1c61a715eb6bfa654c2a64736d42d2be sale_product_recommendation-6.6.0
+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
+aead29923a0444b44ca13ac0261081c5fdebdf86 6.2.0
+6c687b0522c7b41e9d159b8245a8b08a1aac0951 6.4.0
+23e5472decd6217b0bee98fa9cf1e34825b42702 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+aead29923a0444b44ca13ac0261081c5fdebdf86 sale_promotion_coupon-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+6c687b0522c7b41e9d159b8245a8b08a1aac0951 sale_promotion_coupon-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+23e5472decd6217b0bee98fa9cf1e34825b42702 sale_promotion_coupon-6.6.0
+195a7def6bcf08e863c8f183ef1e4237be8fb3ad 6.6.0
+0000000000000000000000000000000000000000 6.6.0
+195a7def6bcf08e863c8f183ef1e4237be8fb3ad sale_promotion_coupon_payment-6.6.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
+1cea363e1a055df3a2d739ee7165cb12f4e0da74 6.2.0
+d3d5f56b3c5859b3a6c742d4639680ac8dbfdca0 6.4.0
+663d96480f336b6ef4b9b9e60623d4ea197f0673 6.6.0
+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.2.0
+1cea363e1a055df3a2d739ee7165cb12f4e0da74 sale_promotion-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+d3d5f56b3c5859b3a6c742d4639680ac8dbfdca0 sale_promotion-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+663d96480f336b6ef4b9b9e60623d4ea197f0673 sale_promotion-6.6.0
+2a228469da4bed16d7d4c457abbc807cc573c265 5.4.0
+56454423ca2d4e487200814673f5ecd8fc980efd 5.6.0
+d805b804f29e407ea4b0f69efcafe6a61865362c 5.8.0
+31c032243180722071056f4e2e2a1d4ae4df953f 6.0.0
+b2a816d82cf69524c1293c3bd4de02a9f3445194 6.2.0
+214173dbe36875ca183700433ef3758e6f889235 6.4.0
+923d81cbda9d4d0b4e308fd72ed52680ab72af35 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+b2a816d82cf69524c1293c3bd4de02a9f3445194 sale_secondary_unit-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+214173dbe36875ca183700433ef3758e6f889235 sale_secondary_unit-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+923d81cbda9d4d0b4e308fd72ed52680ab72af35 sale_secondary_unit-6.6.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
+20fad95e052905da73102c0fea52b3e7e3eeb68f 6.2.0
+7acd6d4c1f7b2bb870f62827d78acf14135fc602 6.4.0
+669610bb236c5060c194f0e12ab873df71647d52 6.6.0
+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.2.0
+20fad95e052905da73102c0fea52b3e7e3eeb68f sale_shipment_cost-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+7acd6d4c1f7b2bb870f62827d78acf14135fc602 sale_shipment_cost-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+669610bb236c5060c194f0e12ab873df71647d52 sale_shipment_cost-6.6.0
+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
+5e4ce2cb6dd127fc4b76454e95cccbf4ee88f090 6.2.0
+6701a829ded00feb53d7be272c890dc51d80ad07 6.4.0
+103d069a79ade9bfe05f1d9471a457246f9821b8 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+5e4ce2cb6dd127fc4b76454e95cccbf4ee88f090 sale_shipment_grouping-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+6701a829ded00feb53d7be272c890dc51d80ad07 sale_shipment_grouping-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+103d069a79ade9bfe05f1d9471a457246f9821b8 sale_shipment_grouping-6.6.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
+b9fe1472cfc3fa75057b66bd6c883d397c724468 6.2.0
+ea420cc03e2ba3e82c79fbda1fa3722ae2af2cef 6.4.0
+fd83e20dcaa2f6b9a2c035f10be6afd3df48b755 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+b9fe1472cfc3fa75057b66bd6c883d397c724468 sale_shipment_tolerance-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+ea420cc03e2ba3e82c79fbda1fa3722ae2af2cef sale_shipment_tolerance-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+fd83e20dcaa2f6b9a2c035f10be6afd3df48b755 sale_shipment_tolerance-6.6.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
+292c9f8616be7cb1d68fd7fcefa2e653e11b238d 6.2.0
+c18743a20433628eae3b238b640be56388d2db0f 6.4.0
+12af663c366799707478a85f486358d70f5ebc1f 6.6.0
+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.2.0
+292c9f8616be7cb1d68fd7fcefa2e653e11b238d sale_stock_quantity-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+c18743a20433628eae3b238b640be56388d2db0f sale_stock_quantity-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+12af663c366799707478a85f486358d70f5ebc1f sale_stock_quantity-6.6.0
+75517bd9657c0e40c5ec4e9e3e37df1586f4dc90 5.0.0
+b3dc75efc82dbe9433628ecb62de248d27db2ad3 5.2.0
+6f9c41ec5642ab214b9ec0f72d2fb9bf0c94e98d 5.4.0
+3bcc53cee134356e3bb99c6c2deb4c54d7121a99 5.6.0
+d2667ef655e3fcd2bce97d45493dd3ca2d39981c 5.8.0
+4de0f53738952b064ded56a22ba8f7dd8f3c78ff 6.0.0
+12ff8521b7e3b63cd6a7cdbe1ff38fd570df87e7 6.2.0
+e3838bf193a7b7ecc5bd972d9238af1e64a90e04 6.4.0
+7b7bfdcc1ad2cfcc550a957802114153dae6524b 6.6.0
+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.2.0
+12ff8521b7e3b63cd6a7cdbe1ff38fd570df87e7 sale_subscription_asset-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+e3838bf193a7b7ecc5bd972d9238af1e64a90e04 sale_subscription_asset-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+7b7bfdcc1ad2cfcc550a957802114153dae6524b sale_subscription_asset-6.6.0
+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
+e5190aae89d423191f15f500f42a0f35cb21f117 6.2.0
+9af60e26dd79dd30e6ec0609e365344b1250d29c 6.4.0
+6f2ab30e556d71e08663bea79defaf21d54ed5d4 6.6.0
+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.2.0
+e5190aae89d423191f15f500f42a0f35cb21f117 sale_subscription-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+9af60e26dd79dd30e6ec0609e365344b1250d29c sale_subscription-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+6f2ab30e556d71e08663bea79defaf21d54ed5d4 sale_subscription-6.6.0
+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
+f2df468193a63bb6d56083ceb853bb3c390aa7de 6.2.0
+fcecdacba07c2ea68eb54c8e857b4f43f7141ad5 6.4.0
+9ffe7d3e158e5862d04def1538f25bdb2161c236 6.6.0
+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.2.0
+f2df468193a63bb6d56083ceb853bb3c390aa7de sale_supply_drop_shipment-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+fcecdacba07c2ea68eb54c8e857b4f43f7141ad5 sale_supply_drop_shipment-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+9ffe7d3e158e5862d04def1538f25bdb2161c236 sale_supply_drop_shipment-6.6.0
+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
+432ecd49808d54aa33187cd80d6f63157627655a 6.2.0
+b6805e6286b9a01d8ff771dcfce9df03b44f8361 6.4.0
+b619018431c13efb0842ef327ac8bffe0f6d3f82 6.6.0
+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.2.0
+432ecd49808d54aa33187cd80d6f63157627655a sale_supply-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+b6805e6286b9a01d8ff771dcfce9df03b44f8361 sale_supply-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+b619018431c13efb0842ef327ac8bffe0f6d3f82 sale_supply-6.6.0
+f62f4846d82f2c05110d92ddb65f764478df50d4 5.6.0
+2e4a3b14e265050e2df36c1c96b03fd246a5da6e 5.8.0
+2081017ba6e796df571eb28475f82ada5ab9c27f 6.0.0
+f5f4a83af1aeb986953896e5998e493dc0409e8a 6.2.0
+0796eba2e4ce9cbe1a55eae318928f5d1c677cad 6.4.0
+7fd73f7e728815f79790e1900fab8191a99ac4bb 6.6.0
+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.2.0
+f5f4a83af1aeb986953896e5998e493dc0409e8a sale_supply_production-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+0796eba2e4ce9cbe1a55eae318928f5d1c677cad sale_supply_production-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+7fd73f7e728815f79790e1900fab8191a99ac4bb sale_supply_production-6.6.0
+2ecdd7815e6c21be61cd051a6a9e8b717f070a88 5.8.0
+8ca8057e893a91132d0cd825f4d657f33d7ea0e7 6.0.0
+42401c72c3a82685174dba5a81aaebaa4f624fb1 6.2.0
+813ad0081e08f2bc3bd5625b9e78a4e08f5c2151 6.4.0
+279eb9b4bf692ed19998700b08ce14fa33d925af 6.6.0
+0000000000000000000000000000000000000000 5.8.0
+2ecdd7815e6c21be61cd051a6a9e8b717f070a88 stock_assign_manual-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+8ca8057e893a91132d0cd825f4d657f33d7ea0e7 stock_assign_manual-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+42401c72c3a82685174dba5a81aaebaa4f624fb1 stock_assign_manual-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+813ad0081e08f2bc3bd5625b9e78a4e08f5c2151 stock_assign_manual-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+279eb9b4bf692ed19998700b08ce14fa33d925af stock_assign_manual-6.6.0
+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
+180de67e1814e6ba5e8668158ba9a58b95820b5c 6.2.0
+ae815400b9962362a04e7f2ba15e9f714d605fd5 6.4.0
+0c4fcba19d00c6ab004bb83164acf47473f13dd2 6.6.0
+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.2.0
+180de67e1814e6ba5e8668158ba9a58b95820b5c stock_consignment-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+ae815400b9962362a04e7f2ba15e9f714d605fd5 stock_consignment-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+0c4fcba19d00c6ab004bb83164acf47473f13dd2 stock_consignment-6.6.0
+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
+51e2cca077e6619be7c4ae334286e202daaaf27c 6.2.0
+e997d99e37b7120b7ac28b1b9736a42befef1146 6.4.0
+8bef0994e14f3dddaa9a19ef99917a5a88ec1407 6.6.0
+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.2.0
+51e2cca077e6619be7c4ae334286e202daaaf27c stock_forecast-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+e997d99e37b7120b7ac28b1b9736a42befef1146 stock_forecast-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+8bef0994e14f3dddaa9a19ef99917a5a88ec1407 stock_forecast-6.6.0
+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
+3cdc0696c0f6a6aaf4e767ccfc25971a992340ce 6.2.0
+65d7e83be01e651274bc5eebd98deac8b4afceef 6.4.0
+f83c1c8c757c652767eb7651370f786f0a864e00 6.6.0
+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.2.0
+3cdc0696c0f6a6aaf4e767ccfc25971a992340ce stock-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+65d7e83be01e651274bc5eebd98deac8b4afceef stock-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+f83c1c8c757c652767eb7651370f786f0a864e00 stock-6.6.0
+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
+6cf0c4d8f64ccaedf402800b446718200d74bbcb 6.2.0
+2406bcb73d0867cb64318cb3917d421ae50858a5 6.4.0
+e245f55d75a981d8b7968be54c9faeaa97c61e22 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+6cf0c4d8f64ccaedf402800b446718200d74bbcb stock_inventory_location-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+2406bcb73d0867cb64318cb3917d421ae50858a5 stock_inventory_location-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+e245f55d75a981d8b7968be54c9faeaa97c61e22 stock_inventory_location-6.6.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
+3ebb517c91bc0b75b347d4e23fc63234aace7b22 6.2.0
+a71b982ae4381f840823a000af60c3c222c957f0 6.4.0
+26556d44c2fb84b55ef0c6ee513181c56e743148 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+3ebb517c91bc0b75b347d4e23fc63234aace7b22 stock_location_move-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+a71b982ae4381f840823a000af60c3c222c957f0 stock_location_move-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+26556d44c2fb84b55ef0c6ee513181c56e743148 stock_location_move-6.6.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
+613034b9778b85d02ae1585a39e90039f13a3695 6.2.0
+47541d334066316ea3296e4eb2004da55c6b5e4f 6.4.0
+2ba005a00d90302b0bf759cf8528df1fca8bbaec 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+613034b9778b85d02ae1585a39e90039f13a3695 stock_location_sequence-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+47541d334066316ea3296e4eb2004da55c6b5e4f stock_location_sequence-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+2ba005a00d90302b0bf759cf8528df1fca8bbaec stock_location_sequence-6.6.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
+188ebdc1fe97c6427635e6a6f5778c5000ba5938 6.2.0
+b5347defe5e8d03260599fd6e03002022b9a993c 6.4.0
+50613053f4b76964b7bcea9f7894fb77c068b50f 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+188ebdc1fe97c6427635e6a6f5778c5000ba5938 stock_lot-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+b5347defe5e8d03260599fd6e03002022b9a993c stock_lot-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+50613053f4b76964b7bcea9f7894fb77c068b50f stock_lot-6.6.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
+771f2086b196fc5756e7bfcaf52365abd00d10e9 6.2.0
+af1f96f38c986ef0c8b960d83c9725d3c525c709 6.4.0
+2a4f3a2eeb07431a35a32d69ccec9d4d3f5014dc 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+771f2086b196fc5756e7bfcaf52365abd00d10e9 stock_lot_sled-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+af1f96f38c986ef0c8b960d83c9725d3c525c709 stock_lot_sled-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+2a4f3a2eeb07431a35a32d69ccec9d4d3f5014dc stock_lot_sled-6.6.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
+1b88c1efab8e6d8c128b0eed0395603ccb2d1ffd 6.2.0
+e5d8ffaf91c7afd4f809b0bc441827edc8673dda 6.4.0
+3b990739f8071bb9bcc46bfb5f45a2f71532f296 6.6.0
+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.2.0
+1b88c1efab8e6d8c128b0eed0395603ccb2d1ffd stock_lot_unit-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+e5d8ffaf91c7afd4f809b0bc441827edc8673dda stock_lot_unit-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+3b990739f8071bb9bcc46bfb5f45a2f71532f296 stock_lot_unit-6.6.0
+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
+f3109538cd603d85a10e5070ce8a1bfd92416dfe 6.2.0
+260a52bf21527f2e746e08ae3e2eb5d86551fdf2 6.4.0
+b812bca2a752860635219290eca696b83042e406 6.6.0
+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.2.0
+f3109538cd603d85a10e5070ce8a1bfd92416dfe stock_package-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+260a52bf21527f2e746e08ae3e2eb5d86551fdf2 stock_package-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+b812bca2a752860635219290eca696b83042e406 stock_package-6.6.0
+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
+6216cdc125f78a1071e72bb49cc7fcdff2b82667 6.2.0
+053fff25d83a0378a37b43591d864becdb8dd217 6.4.0
+1ec0ff090be4cead1d05df473cf8fbdfe0810c88 6.6.0
+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.2.0
+6216cdc125f78a1071e72bb49cc7fcdff2b82667 stock_package_shipping_dpd-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+053fff25d83a0378a37b43591d864becdb8dd217 stock_package_shipping_dpd-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+1ec0ff090be4cead1d05df473cf8fbdfe0810c88 stock_package_shipping_dpd-6.6.0
+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
+0f981b2c2095bb4284ed6e1abe9e5f076e44bc65 6.2.0
+656bbe82f32db7cc41ba407bb46eb8ef4d78b72d 6.4.0
+81a891f156685cf5afe526044217c806990d462b 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+0f981b2c2095bb4284ed6e1abe9e5f076e44bc65 stock_package_shipping-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+656bbe82f32db7cc41ba407bb46eb8ef4d78b72d stock_package_shipping-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+81a891f156685cf5afe526044217c806990d462b stock_package_shipping-6.6.0
+efe8ad65ecc999176a779e8a5b9506916223081e 6.2.0
+e70bee6490857d56f447491144ef6d6e61bf229a 6.4.0
+dd62e5e8f5838b5653e649ec07968ee07c972f71 6.6.0
+0000000000000000000000000000000000000000 6.2.0
+efe8ad65ecc999176a779e8a5b9506916223081e stock_package_shipping_mygls-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+e70bee6490857d56f447491144ef6d6e61bf229a stock_package_shipping_mygls-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+dd62e5e8f5838b5653e649ec07968ee07c972f71 stock_package_shipping_mygls-6.6.0
+7bdde48affeaf205d5698d453b5ae136c8dcf69a 6.2.0
+85f567bf416a2e725f88c9e68f11cec2fb97ba53 6.4.0
+086fa4d627bd13cea36e72e923ae18e7b387fe12 6.6.0
+0000000000000000000000000000000000000000 6.2.0
+7bdde48affeaf205d5698d453b5ae136c8dcf69a stock_package_shipping_sendcloud-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+85f567bf416a2e725f88c9e68f11cec2fb97ba53 stock_package_shipping_sendcloud-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+086fa4d627bd13cea36e72e923ae18e7b387fe12 stock_package_shipping_sendcloud-6.6.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
+d2df4ecc1213be8c5ff84508ec7c72fa2a38f457 6.2.0
+92b93590f3c5e0fc8520d61181aeb2bfc85af729 6.4.0
+954087b1fe9ed0441b5ac0dbaae3700754422b02 6.6.0
+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.2.0
+d2df4ecc1213be8c5ff84508ec7c72fa2a38f457 stock_package_shipping_ups-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+92b93590f3c5e0fc8520d61181aeb2bfc85af729 stock_package_shipping_ups-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+954087b1fe9ed0441b5ac0dbaae3700754422b02 stock_package_shipping_ups-6.6.0
+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
+18a35510777ea296aff2bdc46fa4fc156fb6a2b6 6.2.0
+8f8e0041380e8a6dded2149eeb2f83993e98cb4f 6.4.0
+11e9e50a83519832fc3a654c6a2893a47af1c852 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+18a35510777ea296aff2bdc46fa4fc156fb6a2b6 stock_product_location-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+8f8e0041380e8a6dded2149eeb2f83993e98cb4f stock_product_location-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+11e9e50a83519832fc3a654c6a2893a47af1c852 stock_product_location-6.6.0
+790271308b23a4856ade0be330ee59b5d69e7e75 6.0.0
+729e05a801e119103c3087b3f8708632d0121ee2 6.2.0
+300d3e729f2ce6c918ea534784d82917315a2e82 6.4.0
+c9f273114e8b76b0154115cb01f9a0345109cf84 6.6.0
+0000000000000000000000000000000000000000 6.0.0
+790271308b23a4856ade0be330ee59b5d69e7e75 stock_quantity_early_planning-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+729e05a801e119103c3087b3f8708632d0121ee2 stock_quantity_early_planning-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+300d3e729f2ce6c918ea534784d82917315a2e82 stock_quantity_early_planning-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+c9f273114e8b76b0154115cb01f9a0345109cf84 stock_quantity_early_planning-6.6.0
+8c7dc4a68eb44600a2e57f380b7fb39e7d4c9bd7 6.0.0
+180fa9e24693b07498ca2994729aa234e5f2f230 6.2.0
+12dbb1ede87b8d90716c7bd3d93116a5ef06cbf1 6.4.0
+693c2fbb45dee895662a6c24d8ebe55e9ca5bb53 6.6.0
+0000000000000000000000000000000000000000 6.0.0
+8c7dc4a68eb44600a2e57f380b7fb39e7d4c9bd7 stock_quantity_issue-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+180fa9e24693b07498ca2994729aa234e5f2f230 stock_quantity_issue-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+12dbb1ede87b8d90716c7bd3d93116a5ef06cbf1 stock_quantity_issue-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+693c2fbb45dee895662a6c24d8ebe55e9ca5bb53 stock_quantity_issue-6.6.0
+5e63bae17297495d2b63041be081e6bb8a69be2e 5.4.0
+83b28ed660ea0a02ba4cbaea22f495f2b3038615 5.6.0
+d7e3a25d15aa72096b29d985483e3caeb1fc4a43 5.8.0
+e55605b40ed71ec25e3079bb9c8b473bf879af58 6.0.0
+f3fd1dcb37f9d934da6f6bb0c31770409a93265f 6.2.0
+b7fb7dc89a758cc91d55f523db7513c6365b7af2 6.4.0
+1ab9ff3f2173cca3d03571d4b090e1e9fa085632 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+f3fd1dcb37f9d934da6f6bb0c31770409a93265f stock_secondary_unit-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+b7fb7dc89a758cc91d55f523db7513c6365b7af2 stock_secondary_unit-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+1ab9ff3f2173cca3d03571d4b090e1e9fa085632 stock_secondary_unit-6.6.0
+e2d7e4135cc43091843e096a227cb69ded3b425a 6.0.0
+e86dc3d9aaf74d02f4d76b7b39be6cccc45df90a 6.2.0
+e669817bef263fe9cfc7b9d065f2fd6464c33825 6.4.0
+3c296d4df695e3b1b0e8a13d54e767db5b0b6aec 6.6.0
+0000000000000000000000000000000000000000 6.0.0
+e2d7e4135cc43091843e096a227cb69ded3b425a stock_shipment_cost-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+e86dc3d9aaf74d02f4d76b7b39be6cccc45df90a stock_shipment_cost-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+e669817bef263fe9cfc7b9d065f2fd6464c33825 stock_shipment_cost-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+3c296d4df695e3b1b0e8a13d54e767db5b0b6aec stock_shipment_cost-6.6.0
+738617ef9100cb2bca45596cdaa48c75ad3cfd5e 6.4.0
+ffcd53cff4353e6d17547b5f7d31e2ef2c5ea1b2 6.6.0
+0000000000000000000000000000000000000000 6.4.0
+738617ef9100cb2bca45596cdaa48c75ad3cfd5e stock_shipment_cost_weight-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+ffcd53cff4353e6d17547b5f7d31e2ef2c5ea1b2 stock_shipment_cost_weight-6.6.0
+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
+63c1d22cdd2cb1a4ebc8c3b1e71d3b18487060d2 6.2.0
+d823ffc0ccd4eb62d5621560582b03253fddb346 6.4.0
+a4431f200ae5d4e89fb90795c88258261156220d 6.6.0
+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.2.0
+63c1d22cdd2cb1a4ebc8c3b1e71d3b18487060d2 stock_shipment_measurements-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+d823ffc0ccd4eb62d5621560582b03253fddb346 stock_shipment_measurements-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+a4431f200ae5d4e89fb90795c88258261156220d stock_shipment_measurements-6.6.0
+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
+5cda0f5b743d0d42a58187e5d38585e5e4ec7f1d 6.2.0
+3e649b6f6f2a16621caa05565ffcc8934bcb308e 6.4.0
+ca9aef457838d9bae9cddc270e83239c3d08dfde 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+5cda0f5b743d0d42a58187e5d38585e5e4ec7f1d stock_split-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+3e649b6f6f2a16621caa05565ffcc8934bcb308e stock_split-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+ca9aef457838d9bae9cddc270e83239c3d08dfde stock_split-6.6.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
+a19ed98c7d062115451f9ed8d1e5c09017cd6b72 6.2.0
+ec2dcacd13e91cae985e8a259459a2a1c1185cae 6.4.0
+49793239a5c3e08cb3dd39e43642826b3f692f26 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+a19ed98c7d062115451f9ed8d1e5c09017cd6b72 stock_supply_day-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+ec2dcacd13e91cae985e8a259459a2a1c1185cae stock_supply_day-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+49793239a5c3e08cb3dd39e43642826b3f692f26 stock_supply_day-6.6.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
+e979007c21a4054f31741b30aed287cd5a638ebe 6.2.0
+91add9ae71e1343bccacf5479b71eb0108eb4de1 6.4.0
+1c7acdc192cc44cb913b7aa9165062b1cb1d8873 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+e979007c21a4054f31741b30aed287cd5a638ebe stock_supply_forecast-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+91add9ae71e1343bccacf5479b71eb0108eb4de1 stock_supply_forecast-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+1c7acdc192cc44cb913b7aa9165062b1cb1d8873 stock_supply_forecast-6.6.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
+0a8b4ee3edc6e4e4e128884c435a47108ef30ba2 6.2.0
+e87dde891cebd2a9c913e1d4ed1884010123e740 6.4.0
+833a1c72275774e303e72d99b8c79f61a4aa873b 6.6.0
+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.2.0
+0a8b4ee3edc6e4e4e128884c435a47108ef30ba2 stock_supply-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+e87dde891cebd2a9c913e1d4ed1884010123e740 stock_supply-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+833a1c72275774e303e72d99b8c79f61a4aa873b stock_supply-6.6.0
+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
+6311d85f112ab42e976db5964c3b8a88f71c609d 6.2.0
+df757189f2c2803cbd60aa4646ec073712ad2a72 6.4.0
+a10a03c01c293c3d60338c0cdf255e645ae582bc 6.6.0
+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.2.0
+6311d85f112ab42e976db5964c3b8a88f71c609d stock_supply_production-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+df757189f2c2803cbd60aa4646ec073712ad2a72 stock_supply_production-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+a10a03c01c293c3d60338c0cdf255e645ae582bc stock_supply_production-6.6.0
+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
+c7e966206f80f8ec35d48cada0dbf93603d2ba58 6.2.0
+8326eead85e5b3dbae373141494cf52ac0ee1868 6.4.0
+0e2e8692cf07cdbc798c4ba525b7184633c26635 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+c7e966206f80f8ec35d48cada0dbf93603d2ba58 timesheet_cost-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+8326eead85e5b3dbae373141494cf52ac0ee1868 timesheet_cost-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+0e2e8692cf07cdbc798c4ba525b7184633c26635 timesheet_cost-6.6.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
+562ea339e5f31405a6835b76cd0b0f85541bbe0f 6.2.0
+3c80653500553e4f032caf920c5e0b515dfbdcf0 6.4.0
+c16ea65a1df9fc825f2f929cf47e733dadc73b80 6.6.0
+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.2.0
+562ea339e5f31405a6835b76cd0b0f85541bbe0f timesheet-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+3c80653500553e4f032caf920c5e0b515dfbdcf0 timesheet-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+c16ea65a1df9fc825f2f929cf47e733dadc73b80 timesheet-6.6.0
+0f3d5527aad7e83e07c84b19983b86f5b580d9b9 5.2.0
+32c3f6707c841e89eaa8e1200b4ed4b4b8c2510d 5.4.0
+65a1ddcc0b7d681c785f9260aa11e9c9a9b3f74b 5.6.0
+8766a61dd6f885faa2bed9eaa21c307412674989 5.8.0
+5c50392d0b77f4f5c1f76ece0997ec73591e887c 6.0.0
+111e976e7d587ab314808f3be9508fb45fcb7218 6.2.0
+8b0f3f4c817cbf75622b0e2cca36c7d32a2e71ca 6.4.0
+9a8161d1a043fa99953350890026644a36adc927 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+111e976e7d587ab314808f3be9508fb45fcb7218 user_role-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+8b0f3f4c817cbf75622b0e2cca36c7d32a2e71ca user_role-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+9a8161d1a043fa99953350890026644a36adc927 user_role-6.6.0
+cc6273db844d391455840a0cb63fbd8e78b704c7 5.8.0
+4020d5ca9497c14dfc273676d49363650eb8da80 6.0.0
+2f7384935c9a660fe3e324dd80cae3231058dbfd 6.2.0
+2c401c41ecfbb40b9d175ea27ead1dfc28808d7d 6.4.0
+2e6be173a48ec7586d87bf8d4277d90e45f9e421 6.6.0
+0000000000000000000000000000000000000000 5.8.0
+cc6273db844d391455840a0cb63fbd8e78b704c7 web_shop-5.8.0
+0000000000000000000000000000000000000000 6.0.0
+4020d5ca9497c14dfc273676d49363650eb8da80 web_shop-6.0.0
+0000000000000000000000000000000000000000 6.2.0
+2f7384935c9a660fe3e324dd80cae3231058dbfd web_shop-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+2c401c41ecfbb40b9d175ea27ead1dfc28808d7d web_shop-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+2e6be173a48ec7586d87bf8d4277d90e45f9e421 web_shop-6.6.0
+0fa3353dd8f6ecd194c8850181ed067e33f12a9c 6.2.0
+48e0025a6f396470511abd211e8454cf5b007b68 6.4.0
+fefaf7d877521704862965f443572c2df19d0fa0 6.6.0
+0000000000000000000000000000000000000000 6.2.0
+0fa3353dd8f6ecd194c8850181ed067e33f12a9c web_shop_shopify-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+48e0025a6f396470511abd211e8454cf5b007b68 web_shop_shopify-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+fefaf7d877521704862965f443572c2df19d0fa0 web_shop_shopify-6.6.0
+bfc8e45097fc0e414744408e96708fdf5d2b33a1 5.8.0
+2efa183d80e356d0c11731819456b8dd9bc586db 6.0.0
+68ad2bbc8a5c7be8f7e28abfc29643c50edeae72 6.2.0
+4c49fb91d23f62bcec4079bd4329cc6011a0762d 6.4.0
+a1f0befe30d33598a618410c7ab38831ae8d99b9 6.6.0
+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.2.0
+68ad2bbc8a5c7be8f7e28abfc29643c50edeae72 web_shop_vue_storefront-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+4c49fb91d23f62bcec4079bd4329cc6011a0762d web_shop_vue_storefront-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+a1f0befe30d33598a618410c7ab38831ae8d99b9 web_shop_vue_storefront-6.6.0
+0a5ab9e8e526e89b69c1aadb73127da0759edc27 5.8.0
+4b01e563d74ede2cd6ac3c0ae8bd597a963c21a3 6.0.0
+4aec6b591d561476f821e4b7696fdeb2445649a0 6.2.0
+13fb09e13f9961147b3fafd7a4acda34aa782057 6.4.0
+69ebe443a0a7202973e896d6a44a62a2fff29615 6.6.0
+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.2.0
+4aec6b591d561476f821e4b7696fdeb2445649a0 web_shop_vue_storefront_stripe-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+13fb09e13f9961147b3fafd7a4acda34aa782057 web_shop_vue_storefront_stripe-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+69ebe443a0a7202973e896d6a44a62a2fff29615 web_shop_vue_storefront_stripe-6.6.0
+d1340478469878c66528aac5cec001841d14ca5a 5.2.0
+bed84c6dd812463897dc9cca5b7909f6ea4651a4 5.4.0
+e37a9b2291b9b60d453a9eabc894d21b5aeca097 5.6.0
+c3046a83c61339a6310b8cf56c2e4dddd59a0675 5.8.0
+0d2662846f667e44e2831a271becf86f8868c9a5 6.0.0
+5a39f9619caf2338d2b86a46f16154a8e29d2830 6.2.0
+b27e5df8f64e7e96c3b895ec7090eb1bb9166eaa 6.4.0
+cd182550e175f7de15c5940fb446d72895f68a31 6.6.0
+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.2.0
+5a39f9619caf2338d2b86a46f16154a8e29d2830 web_shortener-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+b27e5df8f64e7e96c3b895ec7090eb1bb9166eaa web_shortener-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+cd182550e175f7de15c5940fb446d72895f68a31 web_shortener-6.6.0
+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
+355cdcd27f958fbd7e3bdd021c238283b3f0f539 6.2.0
+b81b890c871cea5a9a3fb734af72452f59969c32 6.4.0
+a9dab1237717b85084d19158a7d487d0d9adbfb4 6.6.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
+0000000000000000000000000000000000000000 6.2.0
+355cdcd27f958fbd7e3bdd021c238283b3f0f539 web_user-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+b81b890c871cea5a9a3fb734af72452f59969c32 web_user-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+a9dab1237717b85084d19158a7d487d0d9adbfb4 web_user-6.6.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
+286ac00ea47d420641bf79917025421a90a5d353 6.2.0
+1310030ca59a2d88a3995cdc5874e9c4a57c5854 6.4.0
+051cf4dfddf8c0e15109b4a74554a910cc28c6c1 6.6.0
+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.2.0
+286ac00ea47d420641bf79917025421a90a5d353 proteus-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+1310030ca59a2d88a3995cdc5874e9c4a57c5854 proteus-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+051cf4dfddf8c0e15109b4a74554a910cc28c6c1 proteus-6.6.0
+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
+e6b66ac38f2f3aefeddeba9fc0b3cee375d1f19a 6.2.0
+4a114b18bce58de90577d7975b0c275b45ecdcb0 6.4.0
+1bf438772b1bb9702ebb9bbcbce96f7ab53a94eb 6.6.0
+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.2.0
+e6b66ac38f2f3aefeddeba9fc0b3cee375d1f19a sao-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+4a114b18bce58de90577d7975b0c275b45ecdcb0 sao-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+1bf438772b1bb9702ebb9bbcbce96f7ab53a94eb sao-6.6.0
+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
+77df2082ed44a6655dd151c09cf8a7ca36ec6499 6.2.0
+88192dc708bc13b43a99168c97642106684bbfeb 6.4.0
+312583490fff372849dfb38c7c849325d40bbf81 6.6.0
+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.2.0
+77df2082ed44a6655dd151c09cf8a7ca36ec6499 trytond-gis-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+88192dc708bc13b43a99168c97642106684bbfeb trytond-gis-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+312583490fff372849dfb38c7c849325d40bbf81 trytond-gis-6.6.0
+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
+1252631aa5277267887251090d6e2f7ed6d41503 6.2.0
+2593216de16bfca661479ed068b87fd0e83260e0 6.4.0
+e5934d7675cbdbf6e534ea4a01f9e1d0792e22b4 6.6.0
+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.2.0
+1252631aa5277267887251090d6e2f7ed6d41503 trytond-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+2593216de16bfca661479ed068b87fd0e83260e0 trytond-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+e5934d7675cbdbf6e534ea4a01f9e1d0792e22b4 trytond-6.6.0
+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
+932b5115f37ddb479b4034bf1438e48df198cc05 6.2.0
+4100f887dd4a3d7511c0c0547e766db7845114e3 6.4.0
+f3542b3396f897c2231e629437f528371d3d11db 6.6.0
+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.2.0
+932b5115f37ddb479b4034bf1438e48df198cc05 tryton-6.2.0
+0000000000000000000000000000000000000000 6.4.0
+4100f887dd4a3d7511c0c0547e766db7845114e3 tryton-6.4.0
+0000000000000000000000000000000000000000 6.6.0
+f3542b3396f897c2231e629437f528371d3d11db tryton-6.6.0
diff --git a/modules/sale/.drone.yml b/modules/sale/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale/CHANGELOG b/modules/sale/CHANGELOG
new file mode 100644
index 0000000000..c279c7110e
--- /dev/null
+++ b/modules/sale/CHANGELOG
@@ -0,0 +1,185 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Add sale reporting per region
+* Support warehouse pickup
+* Use MultiValue for product lead time
+* Remove CompanyValueMixin for default lead time
+
+Version 6.4.0 - 2022-05-02
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Add customer currency on party
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-01
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Define default invoice and shipment methods by party
+* Split process method
+* Add general reporting
+* Add reporting per customer category
+
+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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
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..89fb7405fd
--- /dev/null
+++ b/modules/sale/__init__.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.pool import Pool
+
+from . import (
+ configuration, invoice, party, product, sale, sale_reporting, stock)
+
+
+def register():
+ Pool.register(
+ stock.Move,
+ sale.Sale,
+ sale.SaleIgnoredInvoice,
+ sale.SaleRecreatedInvoice,
+ sale.SaleLine,
+ sale.SaleLineTax,
+ sale.SaleLineIgnoredMove,
+ sale.SaleLineRecreatedMove,
+ party.Party,
+ party.PartyCustomerCurrency,
+ party.PartySaleMethod,
+ product.Configuration,
+ product.DefaultLeadTime,
+ product.Template,
+ product.ProductLeadTime,
+ 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.Main,
+ sale_reporting.MainTimeseries,
+ sale_reporting.Customer,
+ sale_reporting.CustomerTimeseries,
+ sale_reporting.CustomerCategory,
+ sale_reporting.CustomerCategoryTimeseries,
+ sale_reporting.CustomerCategoryTree,
+ sale_reporting.Product,
+ sale_reporting.ProductTimeseries,
+ sale_reporting.ProductCategory,
+ sale_reporting.ProductCategoryTimeseries,
+ sale_reporting.ProductCategoryTree,
+ sale_reporting.RegionTree,
+ sale_reporting.Country,
+ sale_reporting.CountryTimeseries,
+ sale_reporting.Subdivision,
+ sale_reporting.SubdivisionTimeseries,
+ sale_reporting.CountryTree,
+ 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.OpenRegionTree,
+ sale_reporting.OpenCountryTree,
+ 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..3a1f68445d
--- /dev/null
+++ b/modules/sale/configuration.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 trytond import backend
+from trytond.model import (
+ ModelSingleton, ModelSQL, ModelView, ValueMixin, fields)
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+from trytond.pool import Pool
+from trytond.pyson import Eval, Id, TimeDelta
+from trytond.tools.multivalue import migrate_property
+
+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",
+ domain=['OR',
+ ('sale_process_after', '=', None),
+ ('sale_process_after', '>=', TimeDelta()),
+ ],
+ 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')),
+ ])
+
+ @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..f5a27699b7
--- /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..37c90a922d
--- /dev/null
+++ b/modules/sale/doc/design.rst
@@ -0,0 +1,273 @@
+******
+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 Regions ` which can be opened to 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 --> Configuration|__
+
+ .. |Sales --> Configuration --> Configuration| replace:: :menuselection:`Sales --> Configuration --> 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..69949ae07d
--- /dev/null
+++ b/modules/sale/doc/index.rst
@@ -0,0 +1,16 @@
+###########
+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
+ releases
diff --git a/modules/sale/doc/releases.rst b/modules/sale/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
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..70163ce90a
--- /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:`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..3b9c6f4e08
--- /dev/null
+++ b/modules/sale/invoice.py
@@ -0,0 +1,162 @@
+# 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')
+ transaction = Transaction()
+ context = transaction.context
+ 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:
+ with transaction.set_context(
+ queue_batch=context.get('queue_batch', True)):
+ 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
+
+ def get_warehouse(self, name):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ warehouse = super().get_warehouse(name)
+ if (not warehouse
+ and isinstance(self.origin, SaleLine)
+ and self.origin.warehouse):
+ warehouse = self.origin.warehouse.id
+ return warehouse
+
+ @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')
+ transaction = Transaction()
+ context = transaction.context
+ 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:
+ with transaction.set_context(
+ queue_batch=context.get('queue_batch', True)):
+ Sale.__queue__.process(sales)
diff --git a/modules/sale/locale/bg.po b/modules/sale/locale/bg.po
new file mode 100644
index 0000000000..2e0e217ffe
--- /dev/null
+++ b/modules/sale/locale/bg.po
@@ -0,0 +1,1691 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Клиенти"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Начин на фактуриране"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Начин на фактурине на продажба"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Начин на изпращане"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Партньор"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Партньор"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Начин на фактурине на продажба"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Начин на фактуриране на продажба"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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 "Ред от продажба"
+
+#, 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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Клиенти"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Име"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Клиенти"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Продукт"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Име"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Продукт"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Валута"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Име"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Продажби"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Продажби"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Начин на фактурине на продажба"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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 "Данъци"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..0467ac1da2
--- /dev/null
+++ b/modules/sale/locale/ca.po
@@ -0,0 +1,1603 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Monedes del client"
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moneda del client"
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Mètode de facturació"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Mètodes de venda"
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Mètode d'enviament"
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moneda del client"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Tercer"
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Mètode de facturació de venda"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Mètode d'enviament de venda"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Temps d'espera per defecte"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Temps d'espera per defecte"
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Temps d'espera"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr "Plantilla"
+
+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 la 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_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.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.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,country:"
+msgid "Country"
+msgstr "País"
+
+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.tree,children:"
+msgid "Children"
+msgstr "Fills"
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Pare"
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Regió"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Fills"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Pare"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Categoria"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Fills"
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Pare"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Pare"
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "La moneda per defecte per les vendes d'aquest tercer."
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"El mètode de facturació de venda predeterminat per al client.\n"
+"Deixar en blanc per utilitzar el valor per defecte de la configuració."
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"El mètode d'enviament de venda predeterminat per al client.\n"
+"Deixar en blanc per utilitzar el valor per defecte de la configuració."
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "La moneda per defecte per les vendes d'aquest tercer."
+
+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_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_country_tree"
+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_category"
+msgid "Sales per Customer Category"
+msgstr "Vendes per categoria de client"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Vendes per categoria de tercer"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Vendes per categoria de 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_main"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Vendes per producte"
+
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Vendes per categoria de producte"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Vendes per categoria de producte"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Vendes per categoria de 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_tree"
+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_country_tree_open"
+msgid "Open Region"
+msgstr "Obre regió"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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 \"%(sale)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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr "Un impost només es pot afegir una vegada a una línia de venda."
+
+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_date"
+msgid "Date"
+msgstr "Data"
+
+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_reporting_time_series"
+msgid "Time Series"
+msgstr "Sèries temporals"
+
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr "Monedes de client per tercer"
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Mètode de venda del tercer"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Temps d'enviament per defecte del producte"
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Temps d'enviament 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.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.country.tree,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.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Informe de vendes per categoria de client"
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Informe de vendes per categoria de client"
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Informe de vendes per categoria de client"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Informe de vendes per client"
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Informes de venda"
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Informes de venda"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Informe de vendes per producte"
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Informe de vendes per categoria de producte"
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Informe de vendes per categoria de producte"
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Informe de vendes per categoria de 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.tree,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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Ingressos"
+
+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..bd2073f06b
--- /dev/null
+++ b/modules/sale/locale/cs.po
@@ -0,0 +1,1645 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Invoices"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Handle Shipment Exception"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Namu"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_date"
+msgid "Date"
+msgstr "Sales"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..6a2d5742b4
--- /dev/null
+++ b/modules/sale/locale/de.po
@@ -0,0 +1,1609 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Kundenwährungen"
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Kundenwährung"
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Rechnungsstellung"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Verkauf Methoden"
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Liefermethode"
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Kundenwährung"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Partei"
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Verkauf Rechnungsstellung"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Verkauf Liefermethode"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standard Beschaffungszeit"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standard Beschaffungszeit"
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Beschaffungszeit"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr "Artikelvorlage"
+
+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 "Logistikstandorte"
+
+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 Warenbewegungen (Domain)"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Warenbewegungen 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 Warenbewegungen"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Warenbewegungen mit Vorbehalt"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Warenbewegungen"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Ignorierte Warenbewegungen"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Neu erstellte Warenbewegungen"
+
+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_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.line,warehouse:"
+msgid "Warehouse"
+msgstr "Logistikstandort"
+
+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 "Warenbewegung"
+
+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 "Warenbewegung"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Verkaufsposition"
+
+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 "Logistikstandort"
+
+msgctxt "field:sale.reporting.country,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.subdivision,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "Region"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr "Region"
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Land"
+
+msgctxt "field:sale.reporting.country.tree,children:"
+msgid "Children"
+msgstr "Untergeordnet (Staaten/Regionen)"
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Übergeordnet (Staat/Region)"
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Region"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Untergeordnet (Kategorien)"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Übergeordnet (Kategorie)"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Untergeordnet (Kategorien)"
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Übergeordnet (Kategorie)"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Übergeordnet (Staat/Region)"
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+msgstr "Teilregionen"
+
+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,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 "Warenbewegungen"
+
+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 "Warenrücknahmen"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Lieferstatus"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Lieferungen"
+
+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 "Logistikstandort"
+
+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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Standardwährung für Verkäufe an diese Partei."
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"Die Standard-Rechnungsstellungsmethode für den Kunden.\n"
+"Leer lassen, um den Standardwert aus den Einstellungen zu verwenden."
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"Die Standard-Liefermethode für den Kunden.\n"
+"Leer lassen, um den Standardwert aus den Einstellungen zu verwenden."
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Standardwährung für Verkäufe an diese Partei."
+
+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_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Verkäufe pro Region"
+
+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_country_tree"
+msgid "Sales per Country"
+msgstr "Verkäufe pro Land"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Verkäufe pro Kunde"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Verkäufe pro Kundenkategorie"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Verkäufe pro Parteikategorie"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Verkäufe pro Kundenkategorie"
+
+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_main"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Verkäufe"
+
+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_category"
+msgid "Sales per Product Category"
+msgstr "Verkäufe pro Artikelkategorie"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Verkäufe pro Artikelkategorie"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Verkäufe pro Artikelkategorie"
+
+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_tree"
+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 "Warenbewegungen"
+
+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_country_tree_open"
+msgid "Open Region"
+msgstr "Region öffnen"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr ""
+"Eine Steuer kann nur einmal zu einer Verkaufsposition hinzugefügt 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_date"
+msgid "Date"
+msgstr "Datum"
+
+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 "Umsatz"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_revenue_trend"
+msgid "Revenue Trend"
+msgstr "Umsatzentwicklung"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_time_series"
+msgid "Time Series"
+msgstr "Zeitreihe"
+
+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"
+" Logistikstandort 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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Benutzer in Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr "Partei Kundenwährung"
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Partei Verkauf Methode"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Artikel Standardbeschaffungszeit"
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Artikelbeschaffungszeit"
+
+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 Warenbewegung"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Verkaufsposition - Neu erstellte Warenbewegung"
+
+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 Land"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkaufsauswertung pro Region"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkaufsauswertung pro Region"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkaufsauswertung pro Land"
+
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkaufsauswertung pro Land"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkaufsauswertung pro Kunde"
+
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Verkaufsauswertung pro Kundenkategorie"
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Verkaufsauswertung pro Kundenkategorie"
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Verkaufsauswertung pro Kundenkategorie"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkaufsauswertung pro Kunde"
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Auswertungen"
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Auswertungen"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkaufsauswertung pro Artikel"
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Verkaufsauswertung pro Artikelkategorie"
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Verkaufsauswertung pro Artikelkategorie"
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Verkaufsauswertung pro Artikelkategorie"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkaufsauswertung pro Artikel"
+
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Verkaufsauswertung pro Region"
+
+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 "Warenbewegungen 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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Umsatz"
+
+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..f1b14772e5
--- /dev/null
+++ b/modules/sale/locale/es.po
@@ -0,0 +1,1602 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Monedas del cliente"
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moneda del cliente"
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Método de facturación"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Métodos de venta"
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Método de envío"
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moneda del cliente"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Tercero"
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Método de facturación de venta"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Método de envío de venta"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiempo de espera por defecto"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiempo de espera por defecto"
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Tiempo de espera"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr "Plantilla"
+
+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 final existencias"
+
+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_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.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 "Periodo"
+
+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.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,country:"
+msgid "Country"
+msgstr "País"
+
+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.tree,children:"
+msgid "Children"
+msgstr "Hijos"
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Región"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Hijos"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Categoría"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Hijos"
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Moneda por defecto para las ventas de este tercero."
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"El método de facturación de venta predeterminado para el cliente.\n"
+"Dejar en blanco para usar el valor predeterminado de la configuración."
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"El método de envío de venta predeterminado para el cliente.\n"
+"Dejar en blanco para usar el valor predeterminado de la configuración."
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Moneda por defecto para las ventas de este tercero."
+
+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_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_country_tree"
+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_category"
+msgid "Sales per Customer Category"
+msgstr "Ventas por categoría de cliente"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Ventas por categoría de tercero"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Ventas por categoría de 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_main"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Ventas por producto"
+
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Ventas por categoría de producto"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Ventas por categoría de producto"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Ventas por categoría de 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_tree"
+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_country_tree_open"
+msgid "Open Region"
+msgstr "Abrir región"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr "Un impuesto solo se puede agregar una vez a una línea de venta."
+
+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_date"
+msgid "Date"
+msgstr "Fecha"
+
+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_reporting_time_series"
+msgid "Time Series"
+msgstr "Series temporales"
+
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr "Monedas de cliente por tercero"
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Método de venta de tercero"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Tiempo de envío defecto del producto"
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Tiempo de envío 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.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.country.tree,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.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Informe de ventas por categoría de cliente"
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Informe de ventas por categoría de cliente"
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Informe de ventas por categoría de cliente"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Informe de ventas por cliente"
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Informes de venta"
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Informes de venta"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Informe de ventas por producto"
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Informe de ventas por categoría de producto"
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Informe de ventas por categoría de producto"
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Informe de ventas por categoría de 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.tree,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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Ingresos"
+
+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..ed4cbdb881
--- /dev/null
+++ b/modules/sale/locale/es_419.po
@@ -0,0 +1,1578 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Devolución"
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr ""
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Devolución"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 ""
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+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_country_tree"
+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_category"
+msgid "Sales per Customer Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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_country_tree_open"
+msgid "Open Region"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr ""
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region.tree,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 ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..431e268297
--- /dev/null
+++ b/modules/sale/locale/et.po
@@ -0,0 +1,1690 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Kliendid"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Arve meetod"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Müügiarve meetod"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Tarnemeetod"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Osapool"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Osapool"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Müügiarve meetod"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Tarnemeetod"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Täitmise aeg"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Täitmise aeg"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Täitmise aeg"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+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_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.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.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,country:"
+msgid "Country"
+msgstr "Riik"
+
+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"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,children:"
+msgid "Children"
+msgstr "Alamjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Ülemjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Regioon"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Alamjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nimi"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Ülemjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Klient"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Toode"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Kategooria"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Alamjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nimi"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Ülemjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Toode"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Valuuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nimi"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Ülemjaotus"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 "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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Müük kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Müük kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Müük kategooria lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Müük kliendi lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Müük"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Müük"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Müük toote lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Müük kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Müük kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Müük kategooria lõikes"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Müük toote lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Avatud regioon"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Kuupäev"
+
+#, 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"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_time_series"
+msgid "Time Series"
+msgstr "Aegrida"
+
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Müügi seadistus - müügi meetod"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Täitmise aeg"
+
+#, 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.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"
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Müügiaruandlus toote lõikes"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Müügi aruandlus kliendi lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Müügi aruandlus kliendi lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Aruandlus"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Aruandlus"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Müügiaruandlus toote lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Müügi aruandlus kategooria lõikes"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Müügiaruandlus toote lõikes"
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,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"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Müügitulu"
+
+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..4fb5d584e4
--- /dev/null
+++ b/modules/sale/locale/fa.po
@@ -0,0 +1,1702 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "مشتریان"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "متد صورتحساب"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "متد صورتحساب فروش"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "متد حمل ونقل"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "نهاد/سازمان"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "متد صورتحساب فروش"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "متد حمل ونقل فروش"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "زمان پیشبرد"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "زمان پیشبرد"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "زمان پیشبرد"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr "کشور"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr "زیرتقسیمات"
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr "زیر مجموعه"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "منبع"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "منطقه"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "مشتری"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "زیر مجموعه"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "نام"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "منبع"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "درآمد"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "مشتری"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "محصول"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "دستهبندی"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "زیر مجموعه"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "نام"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "منبع"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "درآمد"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "محصول"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "واحد پول"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "نام"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "منبع"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "فروش ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "فروش ها"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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\"را لغو یا به حالت پیش "
+"نویس بازنشانی کنید."
+
+msgctxt "model:ir.message,text:msg_sale_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr ""
+
+#, 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_date"
+msgid "Date"
+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 "روند درآمد"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "پیکربندی فروش ؛ متد فروش"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 "گزارش فروش در هر کشور"
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "گزارش فروش در هر کشور"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "گزارش فروش برای هر مشتری"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "گزارش فروش برای هر مشتری"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "گزارش فروش در هر محصول"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "گزارش فروش در هر زیرمجموعه"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "گزارش فروش در هر محصول"
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "درآمد"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..06601cfadc
--- /dev/null
+++ b/modules/sale/locale/fi.po
@@ -0,0 +1,1642 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Invoices"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Handle Shipment Exception"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Sales per Customer"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_date"
+msgid "Date"
+msgstr "Sales"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..6d7769c867
--- /dev/null
+++ b/modules/sale/locale/fr.po
@@ -0,0 +1,1603 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Devises de client"
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Devise de client"
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Méthode de facturation"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Méthodes de vente"
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Méthode d'expédition"
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Devise de client"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Tiers"
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Méthode de facturation de vente"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Méthode d'expédition de vente"
+
+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,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Délai d'éxécution par défaut"
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Délai d'exécution"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr "Modèle"
+
+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 de vente"
+
+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 de vente"
+
+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_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.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.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,country:"
+msgid "Country"
+msgstr "Pays"
+
+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.tree,children:"
+msgid "Children"
+msgstr "Enfants"
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Région"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Enfants"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Catégorie"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Enfants"
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+msgstr "Sous-régions"
+
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Devise par défaut pour les ventes à ce tiers."
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"La méthode de facture de vente par défaut pour le client.\n"
+"Laissez vide pour utiliser la valeur par défaut de la configuration."
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"La méthode d'expédition de vente par défaut pour le client.\n"
+"Laissez vide pour utiliser la valeur par défaut de la configuration."
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Devise par défaut pour les ventes à ce tiers."
+
+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_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_country_tree"
+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_category"
+msgid "Sales per Customer Category"
+msgstr "Ventes par catégorie de client"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Ventes par catégorie de tiers"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Ventes par catégorie de 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_main"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Ventes par produit"
+
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Ventes par catégorie de produit"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Ventes par catégorie de produit"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Ventes par catégorie de 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_tree"
+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_country_tree_open"
+msgid "Open Region"
+msgstr "Ouvrir la région"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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 traitement"
+
+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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr "Une taxe ne peut être ajoutée qu'une seule fois à une ligne de vente."
+
+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_date"
+msgid "Date"
+msgstr "Date"
+
+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_reporting_time_series"
+msgid "Time Series"
+msgstr "Séries temporelles"
+
+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 remplir 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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr "Tiers Devise de client"
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Méthode de vente de tiers"
+
+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.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Délai d’exécution du produit"
+
+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.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.country.tree,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.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Rapport de vente par catégorie de client"
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Rapport de vente par catégorie de client"
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Rapport de vente par catégorie de client"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Rapports de vente par client"
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Rapport de vente"
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Rapport de vente"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Rapports de vente par produit"
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Rapport de vente par catégorie de produit"
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Rapport de vente par catégorie de produit"
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Rapport de vente par catégorie de 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.tree,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ée"
+
+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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Revenu"
+
+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..a2a7635f2d
--- /dev/null
+++ b/modules/sale/locale/hu.po
@@ -0,0 +1,1658 @@
+#
+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"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Értékesítés"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Pénznem"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Számlázás módja"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Vevői rendelések számlázási módja"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Kiszállítás módja"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Pénznem"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Ügyfél"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Cég"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Ügyfél"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Vevői rendelések számlázási módja"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Vevői rendelések szállítási módja"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Alapértelmezett átfutási idő"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Alapértelmezett átfutási idő"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Átfutási idő"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+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_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.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.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,country:"
+msgid "Country"
+msgstr "Ország"
+
+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"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,children:"
+msgid "Children"
+msgstr "Alárendelt rekordok"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Fölérendelt"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Régió"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Vevő"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Kategória"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Kategória"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Alárendelt rekordok"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Név"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Fölérendelt"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Vevő"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Termék"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Kategória"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Kategória"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Alárendelt rekordok"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Név"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Fölérendelt"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Termék"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Pénznem"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Név"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Fölérendelt"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+#, fuzzy
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+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."
+
+#, fuzzy
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+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:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 ""
+"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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Eladások vevőnként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Vevői rendelések"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Eladások termékenként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Eladások termékenként"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Dátum"
+
+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_reporting_time_series"
+msgid "Time Series"
+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 "É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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Vevői rendelések számlázási módja"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Alapértelmezett átfutási idő"
+
+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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Jelentések"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Jelentések"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Eladások termék kategóriánként"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Eladások termék kategóriánként"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Eladások termék kategóriánként"
+
+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"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Árbevétel"
+
+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..5325e9ba20
--- /dev/null
+++ b/modules/sale/locale/id.po
@@ -0,0 +1,1638 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Mata uang"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Metode Faktur"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Metode Faktur"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Status Pengiriman"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Mata uang"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Pihak"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Pihak"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Metode Faktur"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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"
+
+msgctxt "field:product.sale.context,customer:"
+msgid "Customer"
+msgstr "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 "Ringkasan"
+
+msgctxt "field:sale.line,taxes:"
+msgid "Taxes"
+msgstr "Pajak-Pajak"
+
+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_price:"
+msgid "Unit Price"
+msgstr "Harga Satuan"
+
+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.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.subdivision,country:"
+msgid "Country"
+msgstr "Negara"
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.time_series,country:"
+msgid "Country"
+msgstr "Negara"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,children:"
+msgid "Children"
+msgstr "Cabang"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Induk"
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Pelanggan"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Kategori"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Kategori"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Cabang"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Induk"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Pelanggan"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produk"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Kategori"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Kategori"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Cabang"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Induk"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produk"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Mata uang"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nama"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Induk"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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 "Status Pengiriman"
+
+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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Penjualan per Negara"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Penjualan per Pelanggan"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Penjualan per Pelanggan"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Penjualan"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Penjualan"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Penjualan per Produk"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Penjualan per Produk"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+msgid "Sales per Region"
+msgstr "Penjualan per Wilayah"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr ""
+
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Penjualan per Wilayah"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_open"
+msgid "Open Region"
+msgstr "Penjualan per Wilayah"
+
+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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Tanggal"
+
+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_reporting_time_series"
+msgid "Time Series"
+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 "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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Produk-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 ""
+
+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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Pelaporan"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Pelaporan"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Penjualan per Kategori"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Penjualan per Kategori"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Penjualan per Kategori"
+
+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 "Harga Satuan"
+
+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 "Catatan-Catatan"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Pajak-Pajak"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Pendapatan"
+
+msgctxt "view:sale.return_sale.start:"
+msgid "Are you sure to return these/this sale(s)?"
+msgstr "Apakah Anda yakin akan mengembalikan penjualan ini?"
+
+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..c742bb1f8c
--- /dev/null
+++ b/modules/sale/locale/it.po
@@ -0,0 +1,1678 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Clienti"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "metodo di fatturazione"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "metodo di fatturazione vendita"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "metodo di spedizione"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Controparte"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Controparte"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "metodo di fatturazione vendita"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "metodo di spedizione dell'ordine"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "lead time"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "lead time"
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Tempi di consegna"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,lead_time:"
+msgid "Lead Time"
+msgstr "Tempi di consegna"
+
+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"
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr "Magazzini"
+
+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 "Tempi di consegna"
+
+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"
+
+msgctxt "field:sale.line,actual_quantity:"
+msgid "Actual Quantity"
+msgstr "Quantità effettiva"
+
+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 "Categotia UdM 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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Clienti"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Clienti"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Padre"
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Base imponibile precalcolato"
+
+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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 ""
+"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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Vendite"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Vendite"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Data"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "metodo di fatturazione vendita"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "lead time"
+
+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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+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:"
+
+#, fuzzy
+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 "Giorno"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Month"
+msgstr "Mese"
+
+msgctxt "selection:sale.reporting.context,period:"
+msgid "Year"
+msgstr "Anno"
+
+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"
+
+msgctxt "view:sale.handle.invoice.exception.ask:"
+msgid "Choose invoices to recreate:"
+msgstr "Scegliere le fatture da ricreare:"
+
+msgctxt "view:sale.handle.shipment.exception.ask:"
+msgid "Choose move to recreate:"
+msgstr "Scegliere 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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, 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..f0e1d95a69
--- /dev/null
+++ b/modules/sale/locale/lo.po
@@ -0,0 +1,1747 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "ລາຍການເກັບເງິນ"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "ພາກສ່ວນ"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "ພາກສ່ວນ"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Handle Shipment Exception"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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 ""
+
+#, 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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "ຜະລິດຕະພັນ"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "ສະກຸນເງິນ"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "ຊື່"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "ຂາຍ"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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 "ອາກອນ"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..1ef90e29f1
--- /dev/null
+++ b/modules/sale/locale/lt.po
@@ -0,0 +1,1689 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Pirkėjai"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Sąskaita faktūra išrašoma"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Pardavimo sąskaitų faktūrų išrašymo būdas"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Siuntimo būdas"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Kontrahentas"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Pardavimo sąskaitų faktūrų išrašymo būdas"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Siuntimo parduodant būdas"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiekimo laikas"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tiekimo laikas"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Tiekimo laikas"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+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_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.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.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,country:"
+msgid "Country"
+msgstr "Šalis"
+
+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"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,children:"
+msgid "Children"
+msgstr "Dukterinės"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Motininė"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Regionas"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Pirkėjas"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Kategorija"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Kategorija"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Dukterinės"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Pavadinimas"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Motininė"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Pirkėjas"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Prekė"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Kategorija"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Kategorija"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Dukterinės"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Pavadinimas"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Motininė"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Prekė"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Valiuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Pavadinimas"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Motininė"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 "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_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į"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+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ą"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Pardavimai pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Pardavimai pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Pardavimai pagal kategoriją"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Pardavimai pagal pirkėją"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Pardavimai"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Pardavimai"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Pardavimai pagal prekę"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Pardavimai pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Pardavimai pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Pardavimai pagal kategoriją"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Pardavimai pagal prekę"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Atverti regioną"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Data"
+
+#, 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"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_time_series"
+msgid "Time Series"
+msgstr "Laiko serijos"
+
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Organizacijos naudotojas"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Pardavimo metodas"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Tiekimo laikas"
+
+#, 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.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į"
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,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ą"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Pardavimo ataskaita pagal pirkėją"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Ataskaitos"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Ataskaitos"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Pardavimo ataskaita pagal prekę"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Pardavimo ataskaita pagal kategoriją"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Pardavimo ataskaita pagal prekę"
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,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"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Numeris"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Pajamos"
+
+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..4c1cc7722f
--- /dev/null
+++ b/modules/sale/locale/nl.po
@@ -0,0 +1,1604 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.invoice,sale_exception_state:"
+msgid "Exception State"
+msgstr "Uitzondering status"
+
+msgctxt "field:account.invoice,sales:"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "field:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Klant valuta's"
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Klant valuta"
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Factuur afhandeling"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Verkoop methodes"
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Verzend methode"
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Klant valuta"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Relatie"
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Verkoopfactuur methode"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Verkoop Verzendmethode"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standaard doorlooptijd"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Standaard doorlooptijd"
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Doorlooptijd"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr "Template"
+
+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 "Verkoop maateeheid"
+
+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 "Verkoop datum"
+
+msgctxt "field:product.sale.context,stock_date_end:"
+msgid "Stock End Date"
+msgstr "Eind datum 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 "Verkoop maateeheid"
+
+msgctxt "field:sale.configuration,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Verkoopfactuur methode"
+
+msgctxt "field:sale.configuration,sale_process_after:"
+msgid "Process Sale after"
+msgstr "Verwerk verkoop na"
+
+msgctxt "field:sale.configuration,sale_sequence:"
+msgid "Sale Sequence"
+msgstr "Verkoop reeks"
+
+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 "Verkoopfactuur methode"
+
+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 "Verkoop reeks"
+
+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 "Mutaties domein"
+
+msgctxt "field:sale.handle.shipment.exception.ask,recreate_moves:"
+msgid "Recreate Moves"
+msgstr "Mutaties 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 "Omschrijving"
+
+msgctxt "field:sale.line,from_location:"
+msgid "From Location"
+msgstr "Van locatie"
+
+msgctxt "field:sale.line,invoice_lines:"
+msgid "Invoice Lines"
+msgstr "Factuur regels"
+
+msgctxt "field:sale.line,move_done:"
+msgid "Moves Done"
+msgstr "Mutaties gereed"
+
+msgctxt "field:sale.line,move_exception:"
+msgid "Moves Exception"
+msgstr "Mutaties uitzondering"
+
+msgctxt "field:sale.line,moves:"
+msgid "Moves"
+msgstr "Mutaties"
+
+msgctxt "field:sale.line,moves_ignored:"
+msgid "Ignored Moves"
+msgstr "Genegeerde mutaties"
+
+msgctxt "field:sale.line,moves_recreated:"
+msgid "Recreated Moves"
+msgstr "Opnieuw aangemaakte mutaties"
+
+msgctxt "field:sale.line,note:"
+msgid "Note"
+msgstr "Notitie"
+
+msgctxt "field:sale.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.line,product_uom_category:"
+msgid "Product Uom Category"
+msgstr "Categorie mateneenheid"
+
+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 "Verzend datum"
+
+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 "Soort"
+
+msgctxt "field:sale.line,unit:"
+msgid "Unit"
+msgstr "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 "Verkoop regel"
+
+msgctxt "field:sale.line-account.tax,tax:"
+msgid "Tax"
+msgstr "Belasting"
+
+msgctxt "field:sale.line-ignored-stock.move,move:"
+msgid "Move"
+msgstr "Mutatie"
+
+msgctxt "field:sale.line-ignored-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Verkoop regel"
+
+msgctxt "field:sale.line-recreated-stock.move,move:"
+msgid "Move"
+msgstr "Mutatie"
+
+msgctxt "field:sale.line-recreated-stock.move,sale_line:"
+msgid "Sale Line"
+msgstr "Verkoop regel"
+
+msgctxt "field:sale.reporting.context,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Start datum"
+
+msgctxt "field:sale.reporting.context,period:"
+msgid "Period"
+msgstr "Periode"
+
+msgctxt "field:sale.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Eind datum"
+
+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.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,country:"
+msgid "Country"
+msgstr "Land"
+
+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.tree,children:"
+msgid "Children"
+msgstr "Onderliggend"
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Bovenliggend"
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Regio"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Onderliggende niveaus"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Bovenliggend"
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Onderliggende niveaus"
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Bovenliggend"
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Bovenliggend"
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+msgstr "Deelgebied"
+
+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,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.sale,invoice_address:"
+msgid "Invoice Address"
+msgstr "Factuur adres"
+
+msgctxt "field:sale.sale,invoice_method:"
+msgid "Invoice Method"
+msgstr "Factuur afhandeling"
+
+msgctxt "field:sale.sale,invoice_party:"
+msgid "Invoice Party"
+msgstr "Factuur relatie"
+
+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 "Mutaties"
+
+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 "Verkoop datum"
+
+msgctxt "field:sale.sale,shipment_address:"
+msgid "Shipment Address"
+msgstr "Afleveradres"
+
+msgctxt "field:sale.sale,shipment_method:"
+msgid "Shipment Method"
+msgstr "Verzend methode"
+
+msgctxt "field:sale.sale,shipment_party:"
+msgid "Shipment Party"
+msgstr "Verzendende relatie"
+
+msgctxt "field:sale.sale,shipment_returns:"
+msgid "Shipment Returns"
+msgstr "Retour zendingen"
+
+msgctxt "field:sale.sale,shipment_state:"
+msgid "Shipment State"
+msgstr "Verzend status"
+
+msgctxt "field:sale.sale,shipments:"
+msgid "Shipments"
+msgstr "Leveringen"
+
+msgctxt "field:sale.sale,shipping_date:"
+msgid "Shipping Date"
+msgstr "Verzend datum"
+
+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"
+
+msgctxt "field:sale.sale,total_amount_cache:"
+msgid "Total Cache"
+msgstr "Totaal opslag"
+
+msgctxt "field:sale.sale,untaxed_amount:"
+msgid "Untaxed"
+msgstr "Onbelast"
+
+msgctxt "field:sale.sale,untaxed_amount_cache:"
+msgid "Untaxed Cache"
+msgstr "Onbelast opslag"
+
+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 "Uitzondering status"
+
+msgctxt "help:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Standaard valuta voor verkopen aan deze relatie."
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"De standaard verkoop factuur methode voor de klant.\n"
+"Laat leeg om de standaardwaarde uit de configuratie te gebruiken."
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"De standaard verzend methode voor verkopen aan de klant.\n"
+"Laat leeg om de standaardwaarde uit de configuratie te gebruiken."
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr "Standaard valuta voor verkopen aan deze relatie."
+
+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 bevestiging van de 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 de 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 de 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 respijt periode waarin de bevestigde aankoop nog steeds kan worden gereset naar concept.\n"
+"Alleen toegepast als een wachtrij 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 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 verkoop"
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+msgstr "Producten"
+
+msgctxt "model:ir.action,name:act_reporting_country_subdivision_time_series"
+msgid "Sales per Subdivision"
+msgstr "Verkopen per subdivisie"
+
+msgctxt "model:ir.action,name:act_reporting_country_time_series"
+msgid "Sales per Country"
+msgstr "Verkopen per land"
+
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Verkopen per Land"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Verkopen per klant"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Verkopen per klant categorie"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Verkopen per relatie categorie"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Verkopen per klant categorie"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Verkopen per klant"
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Verkopen per product"
+
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Verkopen per product categorie"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Verkopen per product categorie"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Verkopen per product categorie"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Verkopen per product"
+
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+msgid "Sales per Region"
+msgstr "Verkopen per Regio"
+
+msgctxt "model:ir.action,name:act_return_form"
+msgid "Returns"
+msgstr "Terugnames"
+
+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 "Mutaties"
+
+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 "Afhandelen factuur uitzondering"
+
+msgctxt "model:ir.action,name:wizard_modify_header"
+msgid "Modify Header"
+msgstr "Wijzig kop"
+
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Regio"
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_open"
+msgid "Open Region"
+msgstr "Open Regio"
+
+msgctxt "model:ir.action,name:wizard_return_sale"
+msgid "Return Sale"
+msgstr "Terug te nemen verkoop"
+
+msgctxt "model:ir.action,name:wizard_shipment_handle_exception"
+msgid "Handle Shipment Exception"
+msgstr "Afhandelen zending uitzondering"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Alles"
+
+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 klant locatie 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 levering \"%(shipment_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 factuur "
+"adres 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 terug zetten naar concept 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 regel \"%(line)s\" te verwijderen, moet u de verkoop \"%(sale)s\" "
+"annuleren of terug zetten naar concept."
+
+msgctxt "model:ir.message,text:msg_sale_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr ""
+"Een belasting kan slechts eenmaal aan een verkoop regel worden toegevoegd."
+
+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 standaard "
+"grootboekrekening omzet 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 kop van de verkoop \"%(sale)s\" te wijzigen, moet deze in status "
+"\"concept\" 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 mutatie \"%(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 verkoop \"%(sale)s\" te factureren, moet u eerst een grootboekrekening "
+"omzet configureren voor product \"%(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_date"
+msgid "Date"
+msgstr "Datum"
+
+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 "Omzet trent"
+
+msgctxt "model:ir.message,text:msg_sale_reporting_time_series"
+msgid "Time Series"
+msgstr "Tijdreeksen"
+
+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 "Afhandelen factuur uitzondering"
+
+msgctxt "model:ir.model.button,string:sale_handle_shipment_exception_button"
+msgid "Handle Shipment Exception"
+msgstr "Afhandelen zending uitzondering"
+
+msgctxt "model:ir.model.button,string:sale_modify_header_button"
+msgid "Modify Header"
+msgstr "Wijzig kop"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Verwerken"
+
+msgctxt "model:ir.model.button,string:sale_quote_button"
+msgid "Quote"
+msgstr "Offerte"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_subdivision_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_country_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_country_tree_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_customer_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_product_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+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"
+
+msgctxt "model:ir.ui.menu,name:menu_customer"
+msgid "Associated to Sales"
+msgstr "Gekoppeld aan verkoop"
+
+msgctxt "model:ir.ui.menu,name:menu_product"
+msgid "Products"
+msgstr "Producten"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting"
+msgid "Reporting"
+msgstr "Rapportage"
+
+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"
+
+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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr "Klant valuta relatie"
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Relatie verkoop methode"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Product standaard doorlooptijd"
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Product doorlooptijd"
+
+msgctxt "model:product.sale.context,name:"
+msgid "Product Sale Context"
+msgstr "Context product verkoop"
+
+msgctxt "model:res.group,name:group_sale"
+msgid "Sales"
+msgstr "Verkopen"
+
+msgctxt "model:res.group,name:group_sale_admin"
+msgid "Sales Administrator"
+msgstr "Verkoop administratie"
+
+msgctxt "model:sale.configuration,name:"
+msgid "Sale Configuration"
+msgstr "Verkoop instellingen"
+
+msgctxt "model:sale.configuration.sale_method,name:"
+msgid "Sale Configuration Sale Method"
+msgstr "Verkoop configuratie verkoop methode"
+
+msgctxt "model:sale.configuration.sequence,name:"
+msgid "Sale Configuration Sequence"
+msgstr "Verkoop configuratie reeks"
+
+msgctxt "model:sale.handle.invoice.exception.ask,name:"
+msgid "Handle Invoice Exception"
+msgstr "Afhandelen factuur uitzondering"
+
+msgctxt "model:sale.handle.shipment.exception.ask,name:"
+msgid "Handle Shipment Exception"
+msgstr "Afhandelen zending uitzondering"
+
+msgctxt "model:sale.line,name:"
+msgid "Sale Line"
+msgstr "Verkoop regel"
+
+msgctxt "model:sale.line-account.tax,name:"
+msgid "Sale Line - Tax"
+msgstr "Verkoop regel - belasting"
+
+msgctxt "model:sale.line-ignored-stock.move,name:"
+msgid "Sale Line - Ignored Move"
+msgstr "Verkoop regel - genegeerde mutatie"
+
+msgctxt "model:sale.line-recreated-stock.move,name:"
+msgid "Sale Line - Recreated Move"
+msgstr "Verkoop regel - mutatie opnieuw aangemaakt"
+
+msgctxt "model:sale.reporting.context,name:"
+msgid "Sale Reporting Context"
+msgstr "Context verkoop rapportage"
+
+msgctxt "model:sale.reporting.country,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkoop rapportage per land"
+
+msgctxt "model:sale.reporting.country.subdivision,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkoop rapportage per subdivisie"
+
+msgctxt "model:sale.reporting.country.subdivision.time_series,name:"
+msgid "Sale Reporting per Subdivision"
+msgstr "Verkoop rapportage per subdivisie"
+
+msgctxt "model:sale.reporting.country.time_series,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkoop rapportage per land"
+
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Verkoop rapportage per Land"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkoop rapportage per klant"
+
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Verkoop rapportage per klant categorie"
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Verkoop rapportage per klant categorie"
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Verkoop rapportage per klant categorie"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Verkoop rapportage per klant"
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Verkoop rapportage"
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Verkoop rapportage"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkoop rapportage per product"
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Verkoop rapportage per product categorie"
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Verkoop rapportage per product categorie"
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Verkoop rapportage per product categorie"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Verkoop rapportage per product"
+
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Verkoop rapportage per Regio"
+
+msgctxt "model:sale.return_sale.start,name:"
+msgid "Return Sale"
+msgstr "Terug te nemen verkoop"
+
+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 aangemaakt"
+
+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 "Concept 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 N°:"
+
+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 "Na verwerking order"
+
+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 betaling factuur"
+
+msgctxt "selection:sale.sale,shipment_method:"
+msgid "On Order Processed"
+msgstr "Na verwerking order"
+
+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 "Afgerond"
+
+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 mutatie om opnieuw aan te maken:"
+
+msgctxt "view:sale.line:"
+msgid "General"
+msgstr "Algemeen"
+
+msgctxt "view:sale.line:"
+msgid "Notes"
+msgstr "Notities"
+
+msgctxt "view:sale.line:"
+msgid "Taxes"
+msgstr "Belastingen"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Omzet"
+
+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) wilt retourneren?"
+
+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 "Terugname"
diff --git a/modules/sale/locale/pl.po b/modules/sale/locale/pl.po
new file mode 100644
index 0000000000..201cf11623
--- /dev/null
+++ b/modules/sale/locale/pl.po
@@ -0,0 +1,1673 @@
+#
+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ż"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Odbiorcy"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Waluta"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Metoda faktury"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Metoda wysyłki sprzedaży"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Metoda wysyłki"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Waluta"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Strona"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Strona"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Metoda faktury"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Metoda wysyłki sprzedaży"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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"
+
+#, 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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Odbiorcy"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Odbiorcy"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produkt"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produkt"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Waluta"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Sprzedaż"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Sprzedaż"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Data:"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, 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..250b3979bb
--- /dev/null
+++ b/modules/sale/locale/pt.po
@@ -0,0 +1,1683 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Clientes"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Método da fatura"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Método da fatura da venda"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Método da Remessa"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Parceiro"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Parceiro"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Método da fatura da venda"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Método da expedição da venda"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tempo de Espera"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Tempo de Espera"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Tempo de Espera"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+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_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"
+
+#, 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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Clientes"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Clientes"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produto"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produto"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Moeda"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 ""
+"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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Vendas"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Vendas"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Data:"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Configuração de Venda Método de Venda"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Tempo de Espera"
+
+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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, 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..57f266b25c
--- /dev/null
+++ b/modules/sale/locale/ro.po
@@ -0,0 +1,1638 @@
+#
+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"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Clienți"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moneda"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Metoda de facturare"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Metode de Vânzare"
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Metoda de Expediere"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Moneda"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Parte"
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Metoda de facturare al vânzării"
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Metoda de Expediere Marfă"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Timp Implicit de execuţie"
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Timp Implicit de execuţie"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Timp de livrare"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+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_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.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.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,country:"
+msgid "Country"
+msgstr "Țară"
+
+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ă"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,children:"
+msgid "Children"
+msgstr "Copii"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr "Părinte"
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Regiune"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr "Copii"
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Denumire"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr "Părinte"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Categorie"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr "Copii"
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Denumire"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr "Părinte"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Produs"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Denumire"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr "Părinte"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr "Venituri"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"Metoda implicită de facturare pentru client.\n"
+"Lăsaţi gol pentru a utiliza valoarea implicită din configurare."
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"Metoda implicită de facturare pentru client.\n"
+"Lăsaţi gol pentru a utiliza valoarea implicită din configurare."
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 ""
+"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_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ă"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+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_category"
+msgid "Sales per Customer Category"
+msgstr "Vânzări pe Categorii de Clienţi"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Vânzări pe Categorii de Părţi"
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Vânzări pe Categorii de Clienţi"
+
+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_main"
+msgid "Sales"
+msgstr "Vânzări"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Vânzări"
+
+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_category"
+msgid "Sales per Product Category"
+msgstr "Vânzări pe Categorii de Produse"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Vânzări pe Categorie de Produs"
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Vânzări pe Categorie de Produs"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Vânzări pe produs"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Regiune deschisă"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+msgstr "O taxă poate fi adăugată o singură dată la o linie 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ă"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_date"
+msgid "Date"
+msgstr "Data"
+
+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"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_time_series"
+msgid "Time Series"
+msgstr "Seria de timp"
+
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_country_tree_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr "Utilizator în companii"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Metodă de Vânzare al Părţi"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr "Timpul Implicit de Execuţie al Produsului"
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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ă"
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,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.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Raportarea Vânzărilor pe Categorii de Clienţi"
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Raportarea Vânzărilor pe Categorii de Clienţi"
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Raportarea Vânzărilor pe Categorii de Clienţi"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr "Raportarea vânzărilor pe client"
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Raport de Vânzări"
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Raport de Vânzări"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr "Raportarea vânzărilor pe produs"
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Raportarea Vânzărilor pe Categorie de Produse"
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Raportarea Vânzărilor pe Categorie de Produse"
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Raportarea Vânzărilor pe Categorie de Produse"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr "Raportarea vânzărilor pe produs"
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr "Venituri"
+
+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..6e211af3fd
--- /dev/null
+++ b/modules/sale/locale/ru.po
@@ -0,0 +1,1692 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Заказчики"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Метод инвойса"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Метод инвойса продажи"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Метод доставки"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Контрагент"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Организация"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Контрагент"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Метод инвойса продажи"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Способ доставки продажи"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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 "Строка продажи"
+
+#, 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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Заказчики"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Наименование"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Заказчики"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Продукт"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Наименование"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Продукт"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Валюта"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Наименование"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Продажи"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Продажи"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Метод инвойса продажи"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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 "Налоги"
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..711464020b
--- /dev/null
+++ b/modules/sale/locale/sl.po
@@ -0,0 +1,1682 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr "Kupci"
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Način obračuna"
+
+#, fuzzy
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr "Način obračuna"
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Način odpreme"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr "Partner"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr "Partner"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Način obračuna"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Način odpreme"
+
+#, fuzzy
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Dobavni rok"
+
+#, fuzzy
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr "Dobavni rok"
+
+#, fuzzy
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr "Dobavni rok"
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+msgstr ""
+
+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_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"
+
+#, 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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr "Kupci"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "Ime"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr "Kupci"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "Ime"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr "Izdelek"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "Ime"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 "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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Prodajni nalogi"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Prodajni nalogi"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr "Datum:"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr "Konfiguracija načina prodaje"
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:product.lead_time,name:"
+msgid "Product Lead Time"
+msgstr "Dobavni rok"
+
+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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+msgstr ""
+
+#, 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..dce22164dc
--- /dev/null
+++ b/modules/sale/locale/tr.po
@@ -0,0 +1,1641 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Invoices"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "Handle Invoice Exception"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "Handle Shipment Exception"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Sales per Customer"
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_date"
+msgid "Date"
+msgstr "Sales"
+
+#, 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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "Reporting"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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/uk.po b/modules/sale/locale/uk.po
new file mode 100644
index 0000000000..d2df2b49c1
--- /dev/null
+++ b/modules/sale/locale/uk.po
@@ -0,0 +1,1565 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr ""
+
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr ""
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr ""
+
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr ""
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr ""
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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 ""
+
+msgctxt "field:product.sale.context,locations:"
+msgid "Warehouses"
+msgstr ""
+
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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,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 ""
+
+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 ""
+
+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 ""
+
+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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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 ""
+
+msgctxt "model:ir.action,name:act_product"
+msgid "Products"
+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_country_tree"
+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_category"
+msgid "Sales per Customer Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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 ""
+
+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 ""
+
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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 ""
+
+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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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_date"
+msgid "Date"
+msgstr ""
+
+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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr ""
+
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr ""
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr ""
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+msgctxt "model:sale.reporting.region.tree,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 ""
+
+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 ""
+
+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 ""
+
+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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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 ""
+
+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/zh_CN.po b/modules/sale/locale/zh_CN.po
new file mode 100644
index 0000000000..e603e4befc
--- /dev/null
+++ b/modules/sale/locale/zh_CN.po
@@ -0,0 +1,1660 @@
+#
+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:party.party,customer_currencies:"
+msgid "Customer Currencies"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "field:party.party,sale_invoice_method:"
+msgid "Invoice Method"
+msgstr "Invoices"
+
+msgctxt "field:party.party,sale_methods:"
+msgid "Sale Methods"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party,sale_shipment_method:"
+msgid "Shipment Method"
+msgstr "Shipments"
+
+#, fuzzy
+msgctxt "field:party.party.customer_currency,customer_currency:"
+msgid "Customer Currency"
+msgstr "Sales per Customer"
+
+msgctxt "field:party.party.customer_currency,party:"
+msgid "Party"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,party:"
+msgid "Party"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_invoice_method:"
+msgid "Sale Invoice Method"
+msgstr "处理发票异常"
+
+#, fuzzy
+msgctxt "field:party.party.sale_method,sale_shipment_method:"
+msgid "Sale Shipment Method"
+msgstr "处理发货异常"
+
+msgctxt "field:product.configuration,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.configuration.default_lead_time,default_lead_time:"
+msgid "Default Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,lead_time:"
+msgid "Lead Time"
+msgstr ""
+
+msgctxt "field:product.lead_time,template:"
+msgid "Template"
+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_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.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.subdivision,country:"
+msgid "Country"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision,subdivision:"
+msgid "Subdivision"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.subdivision.time_series,country:"
+msgid "Country"
+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.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.country.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.country.tree,region:"
+msgid "Region"
+msgstr "Open Region"
+
+msgctxt "field:sale.reporting.customer,customer:"
+msgid "Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.customer.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.customer.category.tree,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.reporting.customer.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.customer.time_series,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.reporting.product,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.time_series,category:"
+msgid "Category"
+msgstr "Sales per Category"
+
+msgctxt "field:sale.reporting.product.category.tree,children:"
+msgid "Children"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,currency:"
+msgid "Currency"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.product.category.tree,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.reporting.product.category.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.category.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.product.time_series,product:"
+msgid "Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,currency:"
+msgid "Currency"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "field:sale.reporting.region.tree,name:"
+msgid "Name"
+msgstr "纳木"
+
+msgctxt "field:sale.reporting.region.tree,parent:"
+msgid "Parent"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,revenue:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "field:sale.reporting.region.tree,subregions:"
+msgid "Subregions"
+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 ""
+
+#, 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:party.party,customer_currency:"
+msgid "Default currency for sales to this party."
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_method:"
+msgid ""
+"The default sale invoice method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party,sale_shipment_method:"
+msgid ""
+"The default sale shipment method for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:party.party.customer_currency,customer_currency:"
+msgid "Default currency for sales to this party."
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_country_tree"
+msgid "Sales per Country"
+msgstr "Sales per Country"
+
+msgctxt "model:ir.action,name:act_reporting_customer"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_time_series"
+msgid "Sales per Party Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_customer_category_tree"
+msgid "Sales per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_customer_time_series"
+msgid "Sales per Customer"
+msgstr "Sales per Customer"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Sales"
+msgstr "Sales"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Sales"
+msgstr "Sales"
+
+msgctxt "model:ir.action,name:act_reporting_product"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_time_series"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_product_category_tree"
+msgid "Sales per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:ir.action,name:act_reporting_product_time_series"
+msgid "Sales per Product"
+msgstr "Sales per Product"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_region_tree"
+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 "修改标题"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_country_tree_open"
+msgid "Open Region"
+msgstr "Open Region"
+
+#, fuzzy
+msgctxt "model:ir.action,name:wizard_reporting_region_tree_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_line_tax_unique"
+msgid "A tax can be added only once to a sale line."
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_reporting_date"
+msgid "Date"
+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_reporting_time_series"
+msgid "Time Series"
+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_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_country_tree_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_customer_category_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_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_product_category_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_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:party.party.customer_currency,name:"
+msgid "Party Customer Currency"
+msgstr ""
+
+msgctxt "model:party.party.sale_method,name:"
+msgid "Party Sale Method"
+msgstr ""
+
+msgctxt "model:product.configuration.default_lead_time,name:"
+msgid "Product Default Lead Time"
+msgstr ""
+
+msgctxt "model:product.lead_time,name:"
+msgid "Product 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.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 ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.country.tree,name:"
+msgid "Sale Reporting per Country"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.time_series,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.customer.category.tree,name:"
+msgid "Sale Reporting per Customer Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.customer.time_series,name:"
+msgid "Sale Reporting per Customer"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.main,name:"
+msgid "Sale Reporting"
+msgstr "报表"
+
+#, fuzzy
+msgctxt "model:sale.reporting.main.time_series,name:"
+msgid "Sale Reporting"
+msgstr "报表"
+
+msgctxt "model:sale.reporting.product,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.time_series,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+#, fuzzy
+msgctxt "model:sale.reporting.product.category.tree,name:"
+msgid "Sale Reporting per Product Category"
+msgstr "Sales per Category"
+
+msgctxt "model:sale.reporting.product.time_series,name:"
+msgid "Sale Reporting per Product"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:sale.reporting.region.tree,name:"
+msgid "Sale Reporting per Region"
+msgstr "Sales per Category"
+
+#, 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.reporting.country.subdivision.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.subdivision.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.country.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.customer.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.main:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.category.time_series:"
+msgid "Revenue"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.reporting.product.time_series:"
+msgid "Revenue"
+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..5e0be636ed
--- /dev/null
+++ b/modules/sale/message.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+ 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
+
+
+ Date
+
+
+ Time Series
+
+
+ A tax can be added only once to a sale line.
+
+
+
diff --git a/modules/sale/party.py b/modules/sale/party.py
new file mode 100644
index 0000000000..913f837a4a
--- /dev/null
+++ b/modules/sale/party.py
@@ -0,0 +1,126 @@
+# 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, ValueMixin, fields
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+from trytond.modules.party.exceptions import EraseError
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval
+from trytond.transaction import Transaction
+
+customer_currency = fields.Many2One(
+ 'currency.currency', "Customer Currency",
+ help="Default currency for sales to this party.")
+
+
+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'] + [
+ (None, '')]
+ return func
+
+
+class Party(CompanyMultiValueMixin, metaclass=PoolMeta):
+ __name__ = 'party.party'
+
+ sale_invoice_method = fields.MultiValue(fields.Selection(
+ 'get_sale_invoice_method', "Invoice Method",
+ help="The default sale invoice method for the customer.\n"
+ "Leave empty to use the default value from the configuration."))
+ sale_shipment_method = fields.MultiValue(fields.Selection(
+ 'get_sale_shipment_method', "Shipment Method",
+ help="The default sale shipment method for the customer.\n"
+ "Leave empty to use the default value from the configuration."))
+ sale_methods = fields.One2Many(
+ 'party.party.sale_method', 'party', "Sale Methods")
+ customer_currency = fields.MultiValue(customer_currency)
+ customer_currencies = fields.One2Many(
+ 'party.party.customer_currency', 'party', "Customer Currencies")
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in {'sale_invoice_method', 'sale_shipment_method'}:
+ return pool.get('party.party.sale_method')
+ return super().multivalue_model(field)
+
+ get_sale_invoice_method = get_sale_methods('invoice_method')
+ get_sale_shipment_method = get_sale_methods('shipment_method')
+
+ @classmethod
+ def copy(cls, parties, default=None):
+ context = Transaction().context
+ default = default.copy() if default else {}
+ if context.get('_check_access'):
+ fields = [
+ 'sale_methods', 'sale_invoice_method', 'sale_shipment_method']
+ default_values = cls.default_get(fields, with_rec_name=False)
+ for fname in fields:
+ default.setdefault(fname, default_values.get(fname))
+ return super().copy(parties, default=default)
+
+
+class PartySaleMethod(ModelSQL, CompanyValueMixin):
+ "Party Sale Method"
+ __name__ = 'party.party.sale_method'
+
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE',
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'company'})
+ sale_invoice_method = fields.Selection(
+ 'get_sale_invoice_method', "Sale Invoice Method")
+ sale_shipment_method = fields.Selection(
+ 'get_sale_shipment_method', "Sale Shipment Method")
+
+ get_sale_invoice_method = get_sale_methods('invoice_method')
+ get_sale_shipment_method = get_sale_methods('shipment_method')
+
+
+class PartyCustomerCurrency(ModelSQL, ValueMixin):
+ "Party Customer Currency"
+ __name__ = 'party.party.customer_currency'
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE')
+ customer_currency = customer_currency
+
+
+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..23475514bd
--- /dev/null
+++ b/modules/sale/party.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+ 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..d37b436d67
--- /dev/null
+++ b/modules/sale/product.py
@@ -0,0 +1,287 @@
+# 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 sql import Null
+
+from trytond.model import ModelSQL, ModelView, ValueMixin, fields
+from trytond.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval, TimeDelta
+from trytond.transaction import Transaction
+
+default_lead_time = fields.TimeDelta(
+ "Default Lead Time",
+ domain=['OR',
+ ('default_lead_time', '=', None),
+ ('default_lead_time', '>=', TimeDelta()),
+ ],
+ help="The time from confirming the sales order to sending the "
+ "products.\n"
+ "Used for products without a lead time.")
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'product.configuration'
+
+ default_lead_time = fields.MultiValue(default_lead_time)
+
+ @classmethod
+ def default_default_lead_time(cls, **pattern):
+ return datetime.timedelta(0)
+
+
+class DefaultLeadTime(ModelSQL, ValueMixin):
+ "Product Default Lead Time"
+ __name__ = 'product.configuration.default_lead_time'
+ default_lead_time = 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')),
+ ])
+ lead_time = fields.MultiValue(fields.TimeDelta(
+ "Lead Time",
+ domain=['OR',
+ ('lead_time', '=', None),
+ ('lead_time', '>=', TimeDelta()),
+ ],
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ 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')
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'lead_time':
+ return pool.get('product.lead_time')
+ return super().multivalue_model(field)
+
+ @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 ProductLeadTime(ModelSQL, ValueMixin):
+ "Product Lead Time"
+ __name__ = 'product.lead_time'
+
+ template = fields.Many2One(
+ 'product.template', "Template", ondelete='CASCADE')
+ lead_time = fields.TimeDelta(
+ "Lead Time",
+ domain=['OR',
+ ('lead_time', '=', None),
+ ('lead_time', '>=', TimeDelta()),
+ ])
+
+ @classmethod
+ def __register__(cls, module_name):
+ pool = Pool()
+ Template = pool.get('product.template')
+ template = Template.__table__()
+ table = cls.__table__()
+
+ super().__register__(module_name)
+
+ cursor = Transaction().connection.cursor()
+ template_h = Template.__table_handler__(module_name)
+ if template_h.column_exist('lead_time'):
+ cursor.execute(*table.insert(
+ columns=[table.template, table.lead_time],
+ values=template.select(
+ template.id, template.lead_time,
+ where=template.lead_time != Null)))
+ template_h.drop_column('lead_time')
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+
+ sale_price_uom = fields.Function(Monetary(
+ "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:
+ unit_price = product._get_sale_unit_price(quantity=quantity)
+ if unit_price is not None:
+ if uom and product.default_uom.category == uom.category:
+ unit_price = Uom.compute_price(
+ product.default_uom, unit_price, uom)
+ else:
+ unit_price = Uom.compute_price(
+ product.default_uom, unit_price, product.sale_uom)
+ if currency and user.company and unit_price is not None:
+ if user.company.currency != currency:
+ date = Transaction().context.get('sale_date') or today
+ with Transaction().set_context(date=date):
+ unit_price = Currency.compute(
+ user.company.currency, unit_price,
+ currency, round=False)
+ prices[product.id] = unit_price
+ 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:
+ with Transaction().set_context(context=self._context):
+ 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..511039494b
--- /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_symbol(line.quantity, sale.party.lang, line.unit, digits=line.unit.digits) if line.unit else format_number(line.quantity, sale.party.lang)>
+
+
+ <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..3b3943d022
--- /dev/null
+++ b/modules/sale/sale.py
@@ -0,0 +1,2102 @@
+# 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 collections import defaultdict
+from decimal import Decimal
+from functools import partial
+from itertools import chain, groupby
+
+from sql.functions import CharLength
+
+from trytond.i18n import gettext
+from trytond.ir.attachment import AttachmentCopyMixin
+from trytond.ir.note import NoteCopyMixin
+from trytond.model import (
+ Index, Model, ModelSQL, ModelView, Unique, Workflow, fields,
+ sequence_ordered)
+from trytond.model.exceptions import AccessError
+from trytond.modules.account.tax import TaxableMixin
+from trytond.modules.account_product.exceptions import AccountError
+from trytond.modules.company import CompanyReport
+from trytond.modules.company.model import (
+ employee_field, reset_employee, set_employee)
+from trytond.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits, round_price
+from trytond.pool import Pool
+from trytond.pyson import Bool, Eval, If, PYSONEncoder
+from trytond.tools import firstline, sortable_values
+from trytond.transaction import Transaction
+from trytond.wizard import (
+ Button, StateAction, StateTransition, StateView, Wizard)
+
+from .exceptions import (
+ PartyLocationError, SaleQuotationError, SaleValidationError)
+
+
+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):
+ _, operator, operand, *extra = clause
+ nested = clause[0][len(name):]
+ if not nested:
+ if isinstance(clause[2], str):
+ nested = '.rec_name'
+ else:
+ nested = '.id'
+ return [('lines.moves.shipment' + nested,
+ operator, operand, model_name, *extra)]
+ 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,
+ states={
+ 'readonly': (
+ (Eval('state') != 'draft')
+ | Eval('lines', [0])
+ | Eval('party', True)
+ | Eval('invoice_party', True)
+ | Eval('shipment_party', True)),
+ })
+ number = fields.Char("Number", readonly=True)
+ reference = fields.Char("Reference")
+ description = fields.Char('Description',
+ states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ sale_date = fields.Date('Sale Date',
+ states={
+ 'readonly': ~Eval('state').in_(['draft', 'quotation']),
+ 'required': ~Eval('state').in_(
+ ['draft', 'quotation', 'cancelled']),
+ })
+ payment_term = fields.Many2One('account.invoice.payment_term',
+ 'Payment Term',
+ states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ party = fields.Many2One(
+ 'party.party', "Party", required=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('party'))),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'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={'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={'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']),
+ })
+ 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={'company'})
+ shipment_address = fields.Many2One('party.address', 'Shipment Address',
+ domain=['OR',
+ ('party', '=', If(Bool(Eval('shipment_party')),
+ Eval('shipment_party'), Eval('party'))),
+ ('warehouses', 'where', [
+ ('id', '=', Eval('warehouse', -1)),
+ If(Eval('state').in_(['draft', 'quotation']),
+ ('allow_pickup', '=', True),
+ ()),
+ ]),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ warehouse = fields.Many2One('stock.location', 'Warehouse',
+ domain=[('type', '=', 'warehouse')], states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ currency = fields.Many2One('currency.currency', 'Currency', required=True,
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('currency', 0))),
+ })
+ lines = fields.One2Many('sale.line', 'sale', 'Lines', states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends={'party'})
+ comment = fields.Text('Comment')
+ untaxed_amount = fields.Function(Monetary(
+ "Untaxed", digits='currency', currency='currency'), 'get_amount')
+ untaxed_amount_cache = fields.Numeric(
+ "Untaxed Cache", digits='currency', readonly=True)
+ tax_amount = fields.Function(Monetary(
+ "Tax", digits='currency', currency='currency'), 'get_amount')
+ tax_amount_cache = fields.Numeric(
+ "Tax Cache", digits='currency', readonly=True)
+ total_amount = fields.Function(Monetary(
+ "Total", digits='currency', currency='currency'), 'get_amount')
+ total_amount_cache = fields.Numeric(
+ "Total Cache", digits='currency', readonly=True)
+ invoice_method = fields.Selection([
+ ('manual', 'Manual'),
+ ('order', 'On Order Processed'),
+ ('shipment', 'On Shipment Sent'),
+ ],
+ 'Invoice Method', required=True, states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ 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, sort=False)
+ 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',
+ })
+ 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, sort=False)
+ 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.Function(
+ fields.Many2Many('stock.move', None, None, "Moves"),
+ 'get_moves', searcher='search_moves')
+ origin = fields.Reference(
+ "Origin", selection='get_origin',
+ states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ 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']),
+ },
+ 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, sort=False)
+ state_string = state.translated('state')
+
+ @classmethod
+ def __setup__(cls):
+ cls.number.search_unaccented = False
+ cls.reference.search_unaccented = False
+ super(Sale, cls).__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.update({
+ Index(t, (t.reference, Index.Similarity())),
+ Index(t, (t.party, Index.Equality())),
+ Index(
+ t,
+ (t.state, Index.Equality()),
+ where=t.state.in_([
+ 'draft', 'quotation', 'confirmed', 'processing'])),
+ Index(
+ t,
+ (t.invoice_state, Index.Equality()),
+ where=t.state.in_(['none', 'waiting', 'exception'])),
+ Index(
+ t,
+ (t.shipment_state, Index.Equality()),
+ where=t.state.in_(['none', 'waiting', 'exception'])),
+ })
+ 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 order_number(cls, tables):
+ table, _ = tables[None]
+ return [CharLength(table.number), table.number]
+
+ @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'
+
+ @classmethod
+ def default_currency(cls, **pattern):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = pattern.get('company')
+ if not company:
+ company = cls.default_company()
+ if company:
+ return Company(company).currency.id
+
+ @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(
+ 'company', 'party', 'invoice_party', 'shipment_party', 'warehouse',
+ 'payment_term', 'lines')
+ 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(
+ company=self.company.id if self.company else None)
+ if not self.lines:
+ self.currency = self.default_currency(
+ company=self.company.id if self.company else None)
+ if self.party:
+ if not self.invoice_party:
+ self.invoice_address = self.party.address_get(type='invoice')
+ if not self.shipment_party:
+ with Transaction().set_context(
+ warehouse=(
+ self.warehouse.id if self.warehouse else None)):
+ self.shipment_address = self.party.address_get(
+ type='delivery')
+ if self.party.sale_shipment_method:
+ self.shipment_method = self.party.sale_shipment_method
+ else:
+ self.shipment_method = self.default_shipment_method()
+ if self.party.customer_payment_term:
+ self.payment_term = self.party.customer_payment_term
+ if self.party.sale_invoice_method:
+ self.invoice_method = self.party.sale_invoice_method
+ else:
+ self.invoice_method = self.default_invoice_method()
+ if not self.lines:
+ if self.party.customer_currency:
+ self.currency = self.party.customer_currency
+
+ @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', 'warehouse')
+ def on_change_shipment_party(self):
+ with Transaction().set_context(
+ warehouse=self.warehouse.id if self.warehouse else None):
+ 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')
+ if self.party.sale_shipment_method:
+ self.shipment_method = self.party.sale_shipment_method
+
+ @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'
+
+ 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 get_moves(self, name):
+ return [m.id for l in self.lines for m in l.moves]
+
+ @classmethod
+ def search_moves(cls, name, clause):
+ return [('lines.' + clause[0],) + tuple(clause[1:])]
+
+ @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_fields(cls, sales, field_names):
+ super().validate_fields(sales, field_names)
+ cls.check_method(sales, field_names)
+
+ @classmethod
+ def check_method(cls, sales, field_names=None):
+ '''
+ Check the methods.
+ '''
+ if field_names and not (field_names & {
+ 'invoice_method', 'shipment_method'}):
+ return
+ for sale in sales:
+ if (sale.invoice_method == 'shipment'
+ and sale.shipment_method in {'invoice', 'manual'}):
+ raise SaleValidationError(
+ gettext('sale.msg_sale_invalid_method',
+ invoice_method=sale.invoice_method_string,
+ shipment_method=sale.shipment_method_string,
+ sale=sale.rec_name))
+ if (sale.shipment_method == 'invoice'
+ and sale.invoice_method in {'shipment', 'manual'}):
+ raise SaleValidationError(
+ gettext('sale.msg_sale_invalid_method',
+ invoice_method=sale.invoice_method_string,
+ shipment_method=sale.shipment_method_string,
+ sale=sale.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('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))
+ for line in self.lines:
+ if (line.product
+ and line.product.type != 'service'
+ and line.quantity >= 0
+ and not self.shipment_address):
+ raise SaleQuotationError(
+ gettext('sale'
+ '.msg_sale_shipment_address_required_for_quotation',
+ sale=self.rec_name))
+ 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 line.get_move_product_types()):
+ 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 company, c_sales in groupby(sales, key=lambda s: s.company):
+ with Transaction().set_context(company=company.id):
+ today = Date.today()
+ cls.write([s for s in c_sales if not s.sale_date], {
+ 'sale_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
+ 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,
+ 'company': self.company,
+ }
+ values.update(dict(key))
+ shipment = Shipment(**values)
+ if Shipment.__name__ == 'stock.shipment.out':
+ if self.shipment_address == self.warehouse.address:
+ shipment.delivery_address = shipment.warehouse.address
+ else:
+ shipment.delivery_address = self.shipment_address
+ elif Shipment.__name__ == 'stock.shipment.out.return':
+ shipment.contact_address = values['customer'].address_get()
+ return shipment
+
+ 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])
+ shipments.append(shipment)
+ 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)
+
+ @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')
+ transaction = Transaction()
+ context = transaction.context
+ cls.set_sale_date(sales)
+ cls.store_cache(sales)
+ config = Configuration(1)
+ with transaction.set_context(
+ queue_scheduled_at=config.sale_process_after,
+ queue_batch=context.get('queue_batch', True)):
+ 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):
+ states = {'confirmed', 'processing', 'done'}
+ sales = [s for s in sales if s.state in states]
+ cls.lock(sales)
+ cls._process_invoice(sales)
+ cls._process_shipment(sales)
+ cls._process_invoice_shipment_states(sales)
+ cls._process_state(sales)
+
+ @classmethod
+ def _process_invoice(cls, sales):
+ pool = Pool()
+ Invoice = pool.get('account.invoice')
+
+ invoices = {}
+ for sale in sales:
+ invoice = sale.create_invoice()
+ if invoice:
+ invoices[sale] = invoice
+
+ Invoice.save(invoices.values())
+ Invoice.update_taxes(invoices.values())
+ for sale, invoice in invoices.items():
+ sale.copy_resources_to(invoice)
+
+ @classmethod
+ def _process_shipment(cls, sales):
+ pool = Pool()
+ ShipmentOut = pool.get('stock.shipment.out')
+ ShipmentOutReturn = pool.get('stock.shipment.out.return')
+
+ shipments_out, shipments_return = {}, {}
+ for sale in sales:
+ shipments = sale.create_shipment('out')
+ if shipments:
+ shipments_out[sale] = shipments
+ shipments = sale.create_shipment('return')
+ if shipments:
+ shipments_return[sale] = shipments
+
+ shipments = sum((v for v in shipments_out.values()), [])
+ ShipmentOut.save(shipments)
+ ShipmentOut.wait(shipments)
+ for sale, shipments in shipments_out.items():
+ for shipment in shipments:
+ sale.copy_resources_to(shipment)
+
+ shipments = sum((v for v in shipments_return.values()), [])
+ ShipmentOutReturn.save(shipments)
+ for sale, shipments in shipments_return.items():
+ for shipment in shipments:
+ sale.copy_resources_to(shipment)
+
+ @classmethod
+ def _process_invoice_shipment_states(cls, sales):
+ pool = Pool()
+ Line = pool.get('sale.line')
+ lines = []
+ invoice_states, shipment_states = defaultdict(list), defaultdict(list)
+ for sale in sales:
+ invoice_state = sale.get_invoice_state()
+ if sale.invoice_state != invoice_state:
+ invoice_states[invoice_state].append(sale)
+ shipment_state = sale.get_shipment_state()
+ if sale.shipment_state != shipment_state:
+ shipment_states[shipment_state].append(sale)
+
+ for line in sale.lines:
+ line.set_actual_quantity()
+ lines.append(line)
+
+ for invoice_state, sales in invoice_states.items():
+ cls.write(sales, {'invoice_state': invoice_state})
+ for shipment_state, sales in shipment_states.items():
+ cls.write(sales, {'shipment_state': shipment_state})
+ Line.save(lines)
+
+ @classmethod
+ def _process_state(cls, sales):
+ done, process = [], []
+ for sale in sales:
+ 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)
+ 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', required=True)
+ invoice = fields.Many2One(
+ 'account.invoice', "Invoice", ondelete='RESTRICT', 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', required=True)
+ invoice = fields.Many2One(
+ 'account.invoice', "Invoice", ondelete='RESTRICT', required=True)
+
+
+class SaleLine(TaxableMixin, sequence_ordered(), ModelSQL, ModelView):
+ 'Sale Line'
+ __name__ = 'sale.line'
+ sale = fields.Many2One(
+ 'sale.sale', "Sale", ondelete='CASCADE', required=True,
+ states={
+ 'readonly': ((Eval('sale_state') != 'draft')
+ & Bool(Eval('sale'))),
+ })
+ type = fields.Selection([
+ ('line', 'Line'),
+ ('subtotal', 'Subtotal'),
+ ('title', 'Title'),
+ ('comment', 'Comment'),
+ ], "Type", required=True,
+ states={
+ 'readonly': Eval('sale_state') != 'draft',
+ })
+ quantity = fields.Float(
+ "Quantity", digits='unit',
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'required': Eval('type') == 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ })
+ actual_quantity = fields.Float(
+ "Actual Quantity", digits='unit', readonly=True,
+ states={
+ 'invisible': Eval('type') != 'line',
+ })
+ 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)),
+ ])
+ 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={'company'})
+ product_uom_category = fields.Function(
+ fields.Many2One('product.uom.category', 'Product Uom Category'),
+ 'on_change_with_product_uom_category')
+ unit_price = Monetary(
+ "Unit Price", digits=price_digits, currency='currency',
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'required': Eval('type') == 'line',
+ 'readonly': Eval('sale_state') != 'draft'
+ })
+ amount = fields.Function(Monetary(
+ "Amount", digits='currency', currency='currency',
+ states={
+ 'invisible': ~Eval('type').in_(['line', 'subtotal']),
+ },
+ depends={'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={'sale'})
+ 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',
+ }),
+ '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 get_move_product_types(cls):
+ pool = Pool()
+ Move = pool.get('stock.move')
+ return Move.get_product_types()
+
+ @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'
+
+ @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_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', 'unit_price',
+ methods=['_get_context_sale_price'])
+ def compute_unit_price(self):
+ pool = Pool()
+ Product = pool.get('product.product')
+
+ if not self.product:
+ return self.unit_price
+
+ 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 is not None:
+ 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',
+ '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', 'company', 'sale',
+ '_parent_sale.sale_date', '_parent_sale.shipping_date')
+ def planned_shipping_date(self):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ transaction = Transaction()
+ 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:
+ if self.company:
+ company_id = self.company.id
+ else:
+ company_id = transaction.context.get('company')
+ with transaction.set_context(company=company_id):
+ 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')
+
+ 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_number_symbol(
+ self.quantity or 0, self.unit, digits=self.unit.digits)
+ + ' %s @ %s' % (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', required=True)
+ tax = fields.Many2One(
+ 'account.tax', "Tax", ondelete='RESTRICT', required=True)
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_constraints += [
+ ('line_tax_unique', Unique(t, t.line, t.tax),
+ 'sale.msg_sale_line_tax_unique'),
+ ]
+
+
+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', required=True)
+ move = fields.Many2One(
+ 'stock.move', "Move", ondelete='RESTRICT', 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', required=True)
+ move = fields.Many2One(
+ 'stock.move', "Move", ondelete='RESTRICT', 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)
+ with Transaction().set_context(company=header['company'].id):
+ 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'))])
+ 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'))],
+ 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)
+
+ def get_defaults(self, wizard, state_name, fields):
+ return {}
+
+
+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 value_start(self, fields):
+ sale = self.get_sale()
+ values = {}
+ 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]
+ values[fieldname] = value
+
+ # Mimic an empty sale in draft state to get the fields' states right
+ values['lines'] = []
+ return values
+
+ 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..1a56ee32fb
--- /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..48fb7128e1
--- /dev/null
+++ b/modules/sale/sale_reporting.py
@@ -0,0 +1,1155 @@
+# 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 Column, Literal, Null, Union, With
+from sql.aggregate import Count, Max, Min, Sum
+from sql.conditionals import Coalesce
+from sql.functions import Ceil, CurrentTimestamp, DateTrunc, Log, Power
+from sql.operators import Concat
+
+from trytond.i18n import lazy_gettext
+from trytond.model import ModelSQL, ModelView, UnionMixin, fields
+from trytond.modules.currency.fields import Monetary
+from trytond.pool import Pool
+from trytond.pyson import Eval, If
+from trytond.tools import grouped_slice, reduce_ids
+from trytond.transaction import Transaction
+from trytond.wizard import StateAction, StateTransition, Wizard
+
+
+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 = Monetary(
+ lazy_gettext("sale.msg_sale_reporting_revenue"),
+ digits='currency', currency='currency')
+ 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')
+
+ @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 _sale_line(cls, length, index, company_id=None):
+ pool = Pool()
+ Line = pool.get('sale.line')
+ Sale = pool.get('sale.sale')
+
+ line = Line.__table__()
+ sale = Sale.__table__()
+
+ return (line
+ .join(sale, condition=line.sale == sale.id)
+ .select(
+ (line.id * length + index).as_('id'),
+ *cls._sale_line_columns(line, sale),
+ where=sale.state.in_(cls._sale_states())
+ & (sale.company == company_id),
+ ))
+
+ @classmethod
+ def _sale_line_columns(cls, line, sale):
+ return [
+ line.product.as_('product'),
+ Coalesce(line.actual_quantity, line.quantity).as_('quantity'),
+ line.unit_price.as_('unit_price'),
+ Concat('sale.sale,', line.sale).as_('order'),
+ sale.sale_date.as_('date'),
+ sale.company.as_('company'),
+ sale.currency.as_('currency'),
+ sale.party.as_('customer'),
+ sale.warehouse.as_('location'),
+ sale.shipment_address.as_('shipment_address'),
+ ]
+
+ @classmethod
+ def _lines(cls):
+ return [cls._sale_line]
+
+ @classmethod
+ def _joins(cls):
+ pool = Pool()
+ Company = pool.get('company.company')
+ Currency = pool.get('currency.currency')
+ context = Transaction().context
+
+ tables = {}
+ company = context.get('company')
+ lines = cls._lines()
+ tables['line'] = line = Union(*(
+ l(len(lines), i, company) for i, l in enumerate(lines)))
+ tables['line.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(currency_sale,
+ condition=(line.currency == currency_sale.currency)
+ & (currency_sale.start_date <= line.date)
+ & ((currency_sale.end_date == Null)
+ | (currency_sale.end_date > line.date))
+ )
+ .join(company, condition=line.company == company.id)
+ .join(currency_company,
+ condition=(company.currency == currency_company.currency)
+ & (currency_company.start_date <= line.date)
+ & ((currency_company.end_date == Null)
+ | (currency_company.end_date > line.date))
+ ))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ line = tables['line']
+ currency_company = withs['currency_company']
+ currency_sale = withs['currency_sale']
+
+ revenue = cls.revenue.sql_cast(
+ Sum(line.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'),
+ line.company.as_('company'),
+ revenue.as_('revenue'),
+ Count(line.order, 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):
+ line = tables['line']
+ return [line.company]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ pool = Pool()
+ Location = pool.get('stock.location')
+ context = Transaction().context
+ line = tables['line']
+
+ where = Literal(True)
+ from_date = context.get('from_date')
+ if from_date:
+ where &= line.date >= from_date
+ to_date = context.get('to_date')
+ if to_date:
+ where &= line.date <= to_date
+ warehouse = context.get('warehouse')
+ if warehouse:
+ locations = Location.search([
+ ('parent', 'child_of', warehouse),
+ ],
+ query=True)
+ where &= line.location.in_(locations)
+ 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
+
+
+class AbstractTimeseries(Abstract):
+
+ date = fields.Date(lazy_gettext('sale.msg_sale_reporting_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
+ line = tables['line']
+ date = DateTrunc(context.get('period'), line.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')),
+ ()),
+ ])
+ to_date = fields.Date("To Date",
+ domain=[
+ If(Eval('from_date') & Eval('to_date'),
+ ('to_date', '>=', Eval('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 Main(Abstract, ModelView):
+ "Sale Reporting"
+ __name__ = 'sale.reporting.main'
+
+ time_series = fields.Function(fields.One2Many(
+ 'sale.reporting.main.time_series', None,
+ lazy_gettext('sale.msg_sale_reporting_time_series')),
+ 'get_time_series')
+
+ def get_rec_name(self, name):
+ return ''
+
+ def get_time_series(self, name):
+ pool = Pool()
+ Timeseries = pool.get('sale.reporting.main.time_series')
+ return [t.id for t in Timeseries.search([])]
+
+
+class MainTimeseries(AbstractTimeseries, ModelView):
+ "Sale Reporting"
+ __name__ = 'sale.reporting.main.time_series'
+
+
+class CustomerMixin(object):
+ __slots__ = ()
+ customer = fields.Many2One(
+ 'party.party', "Customer",
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'company'})
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ line = tables['line']
+ return super(CustomerMixin, cls)._columns(tables, withs) + [
+ line.customer.as_('customer')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ line = tables['line']
+ return super(CustomerMixin, cls)._group_by(tables, withs) + [
+ line.customer]
+
+ 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',
+ lazy_gettext('sale.msg_sale_reporting_time_series'))
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('customer', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ line = tables['line']
+ return line.customer
+
+ @classmethod
+ def _where(cls, tables, withs):
+ line = tables['line']
+ where = super()._where(tables, withs)
+ where &= line.customer != Null
+ return where
+
+
+class CustomerTimeseries(CustomerMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Customer"
+ __name__ = 'sale.reporting.customer.time_series'
+
+
+class CustomerCategoryMixin:
+ __slots__ = ()
+ category = fields.Many2One('party.category', "Category")
+
+ @classmethod
+ def _joins(cls):
+ pool = Pool()
+ PartyCategory = pool.get('party.party-party.category')
+ from_item, tables, withs = super()._joins()
+ if 'line.customer.party_category' not in tables:
+ party_category = PartyCategory.__table__()
+ tables['line.customer.party_category'] = party_category
+ line = tables['line']
+ from_item = (from_item
+ .join(party_category,
+ condition=line.customer == party_category.party))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ party_category = tables['line.customer.party_category']
+ return super()._columns(tables, withs) + [
+ party_category.category.as_('category')]
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ pool = Pool()
+ Category = pool.get('party.category')
+ category = Category.__table__()
+ line = tables['line']
+ party_category = tables['line.customer.party_category']
+ # Get a stable number of categories over time
+ # by using a number one order bigger.
+ nb_category = category.select(
+ Power(10, (Ceil(Log(Max(category.id))) + Literal(1))))
+ return Min(line.id * nb_category + party_category.id)
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ party_category = tables['line.customer.party_category']
+ return super()._group_by(tables, withs) + [party_category.category]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ party_category = tables['line.customer.party_category']
+ where = super()._where(tables, withs)
+ where &= party_category.category != Null
+ return where
+
+ def get_rec_name(self, name):
+ return self.category.rec_name if self.category else None
+
+
+class CustomerCategory(CustomerCategoryMixin, Abstract, ModelView):
+ "Sale Reporting per Customer Category"
+ __name__ = 'sale.reporting.customer.category'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.customer.category.time_series', 'category',
+ lazy_gettext('sale.msg_sale_reporting_time_series'))
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('category', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ party_category = tables['line.customer.party_category']
+ return party_category.category
+
+
+class CustomerCategoryTimeseries(
+ CustomerCategoryMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Customer Category"
+ __name__ = 'sale.reporting.customer.category.time_series'
+
+
+class CustomerCategoryTree(ModelSQL, ModelView):
+ "Sale Reporting per Customer Category"
+ __name__ = 'sale.reporting.customer.category.tree'
+
+ name = fields.Function(fields.Char("Name"), 'get_name')
+ parent = fields.Many2One('sale.reporting.customer.category.tree', "Parent")
+ children = fields.One2Many(
+ 'sale.reporting.customer.category.tree', 'parent', "Children")
+ revenue = fields.Function(Monetary(
+ "Revenue", digits='currency', currency='currency'), 'get_total')
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"), 'get_currency')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('name', 'ASC'))
+
+ @classmethod
+ def table_query(cls):
+ pool = Pool()
+ Category = pool.get('party.category')
+ return Category.__table__()
+
+ @classmethod
+ def get_name(cls, categories, name):
+ pool = Pool()
+ Category = pool.get('party.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('party.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()
+ ReportingCustomerCategory = pool.get(
+ 'sale.reporting.customer.category')
+ table = cls.__table__()
+ reporting_product_category = ReportingCustomerCategory.__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_customer_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_product_category.id, sub_ids)
+ cursor.execute(
+ *reporting_product_category.select(
+ reporting_product_category.id, where=where))
+ reporting_customer_categories.extend(r for r, in cursor)
+
+ result = {}
+ reporting_product_categories = ReportingCustomerCategory.browse(
+ reporting_customer_categories)
+ for name in names:
+ values = dict.fromkeys(ids, 0)
+ values.update(
+ (c.id, getattr(c, name)) for c in reporting_product_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(self, name):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = Transaction().context.get('company')
+ if company:
+ return Company(company).currency.id
+
+
+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',
+ lazy_gettext('sale.msg_sale_reporting_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 ProductCategoryMixin(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()._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()._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()._group_by(tables, withs) + [template_category.category]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ template_category = tables['line.product.template_category']
+ where = super()._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 ProductCategory(ProductCategoryMixin, Abstract, ModelView):
+ "Sale Reporting per Product Category"
+ __name__ = 'sale.reporting.product.category'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.product.category.time_series', 'category',
+ lazy_gettext('sale.msg_sale_reporting_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 ProductCategoryTimeseries(
+ ProductCategoryMixin, AbstractTimeseries, ModelView):
+ "Sale Reporting per Product Category"
+ __name__ = 'sale.reporting.product.category.time_series'
+
+
+class ProductCategoryTree(ModelSQL, ModelView):
+ "Sale Reporting per Product Category"
+ __name__ = 'sale.reporting.product.category.tree'
+
+ name = fields.Function(fields.Char("Name"), 'get_name')
+ parent = fields.Many2One('sale.reporting.product.category.tree', "Parent")
+ children = fields.One2Many(
+ 'sale.reporting.product.category.tree', 'parent', "Children")
+ revenue = fields.Function(Monetary(
+ "Revenue", digits='currency'), 'get_total')
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"), 'get_currency')
+
+ @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()
+ ReportingProductCategory = pool.get('sale.reporting.product.category')
+ table = cls.__table__()
+ reporting_product_category = ReportingProductCategory.__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_product_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_product_category.id, sub_ids)
+ cursor.execute(
+ *reporting_product_category.select(
+ reporting_product_category.id, where=where))
+ reporting_product_categories.extend(r for r, in cursor)
+
+ result = {}
+ reporting_product_categories = ReportingProductCategory.browse(
+ reporting_product_categories)
+ for name in names:
+ values = dict.fromkeys(ids, 0)
+ values.update(
+ (c.id, getattr(c, name)) for c in reporting_product_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(self, name):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = Transaction().context.get('company')
+ if company:
+ return Company(company).currency.id
+
+
+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.shipment_address' not in tables:
+ address = Address.__table__()
+ tables['line.shipment_address'] = address
+ line = tables['line']
+ from_item = (from_item
+ .join(address, condition=line.shipment_address == address.id))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ address = tables['line.shipment_address']
+ return super(CountryMixin, cls)._columns(tables, withs) + [
+ address.country.as_('country')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ address = tables['line.shipment_address']
+ return super(CountryMixin, cls)._group_by(tables, withs) + [
+ address.country]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ address = tables['line.shipment_address']
+ where = super(CountryMixin, cls)._where(tables, withs)
+ where &= address.country != Null
+ return where
+
+
+class RegionTree(ModelSQL, ModelView):
+ "Sale Reporting per Region"
+ __name__ = 'sale.reporting.region.tree'
+
+ name = fields.Function(fields.Char("Name"), 'get_name')
+ parent = fields.Many2One('sale.reporting.region.tree', "Parent")
+ subregions = fields.One2Many(
+ 'sale.reporting.region.tree', 'parent', "Subregions")
+
+ revenue = fields.Function(Monetary(
+ "Revenue", digits='currency'), 'get_total')
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"), 'get_currency')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('name', 'ASC'))
+
+ @classmethod
+ def table_query(cls):
+ pool = Pool()
+ Region = pool.get('country.region')
+ return Region.__table__()
+
+ @classmethod
+ def get_name(cls, regions, name):
+ pool = Pool()
+ Region = pool.get('country.region')
+ regions = Region.browse(regions)
+ return {r.id: r.name for r in regions}
+
+ @classmethod
+ def order_name(cls, tables):
+ pool = Pool()
+ Region = pool.get('country.region')
+ table, _ = tables[None]
+ if 'region' not in tables:
+ region = Region.__table__()
+ tables['region'] = {
+ None: (region, table.id == region.id),
+ }
+ return Region.name.convert_order(
+ 'name', tables['region'], Region)
+
+ @classmethod
+ def get_total(cls, regions, names):
+ pool = Pool()
+ ReportingCountry = pool.get('sale.reporting.country')
+ table = cls.__table__()
+ cursor = Transaction().connection.cursor()
+
+ regions = cls.search([
+ ('parent', 'child_of', [r.id for r in regions]),
+ ])
+ ids = [c.id for c in regions]
+ parents = {}
+ reporting_countries = []
+ 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)
+
+ result = {}
+ reporting_countries = ReportingCountry.search([
+ ('country.region', 'in', [r.id for r in regions]),
+ ])
+ for name in names:
+ values = dict.fromkeys(ids, 0)
+ for reporting_country in reporting_countries:
+ values[reporting_country.country.region.id] += (
+ getattr(reporting_country, name))
+ result[name] = cls._sum_tree(regions, values, parents)
+ return result
+
+ @classmethod
+ def _sum_tree(cls, regions, values, parents):
+ result = values.copy()
+ regions = set((c.id for c in regions))
+ leafs = regions - set(parents.values())
+ while leafs:
+ for region in leafs:
+ regions.remove(region)
+ parent = parents.get(region)
+ if parent in result:
+ result[parent] += result[region]
+ next_leafs = set(regions)
+ for region in regions:
+ parent = parents.get(region)
+ if not parent:
+ continue
+ if parent in next_leafs and parent in regions:
+ next_leafs.remove(parent)
+ leafs = next_leafs
+ return result
+
+ def get_currency(self, name):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = Transaction().context.get('company')
+ if company:
+ return Company(company).currency.id
+
+
+class OpenRegionTree(Wizard):
+ "Open Region"
+ __name__ = 'sale.reporting.region.tree.open'
+
+ start = StateAction('sale.act_reporting_country_tree')
+
+ def do_start(self, action):
+ pool = Pool()
+ Country = pool.get('country.country')
+ CountryTree = pool.get('sale.reporting.country.tree')
+ countries = Country.search([
+ ('region', 'child_of', [r.id for r in self.records], 'parent'),
+ ])
+ ids = [
+ CountryTree.union_shard(c.id, 'sale.reporting.country')
+ for c in countries]
+ data = {
+ 'ids': ids,
+ }
+ name_suffix = ', '.join(r.rec_name for r in self.records[:5])
+ if len(self.records) > 5:
+ name_suffix += ',...'
+ action['name'] += ' (%s)' % name_suffix
+ return action, data
+
+
+class Country(CountryMixin, Abstract):
+ "Sale Reporting per Country"
+ __name__ = 'sale.reporting.country'
+
+ time_series = fields.One2Many(
+ 'sale.reporting.country.time_series', 'country',
+ lazy_gettext('sale.msg_sale_reporting_time_series'))
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('country', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ address = tables['line.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.shipment_address']
+ return super(SubdivisionMixin, cls)._columns(tables, withs) + [
+ address.subdivision.as_('subdivision')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ address = tables['line.shipment_address']
+ return super(SubdivisionMixin, cls)._group_by(tables, withs) + [
+ address.subdivision]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ address = tables['line.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',
+ lazy_gettext('sale.msg_sale_reporting_time_series'))
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('subdivision', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ address = tables['line.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 CountryTree(UnionMixin, Abstract, ModelView):
+ "Sale Reporting per Country"
+ __name__ = 'sale.reporting.country.tree'
+
+ region = fields.Function(fields.Char("Region"), 'get_rec_name')
+ parent = fields.Many2One('sale.reporting.country.tree', "Parent")
+ children = fields.One2Many(
+ 'sale.reporting.country.tree', '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().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 OpenCountryTree(Wizard):
+ "Open Country"
+ __name__ = 'sale.reporting.country.tree.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..a37291793d
--- /dev/null
+++ b/modules/sale/sale_reporting.xml
@@ -0,0 +1,1042 @@
+
+
+
+
+
+
+
+
+
+ sale.reporting.context
+ form
+ sale_reporting_context_form
+
+
+
+
+
+ sale.reporting.main
+ tree
+ sale_reporting_main_list
+
+
+
+ sale.reporting.main
+ graph
+ sale_reporting_main_graph_revenue
+
+
+
+ sale.reporting.main
+ graph
+ sale_reporting_main_graph_number
+
+
+
+ Sales
+ sale.reporting.main
+ sale.reporting.context
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.main.time_series
+ tree
+ sale_reporting_main_time_series_list
+
+
+
+ sale.reporting.main.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.main.time_series
+ graph
+ sale_reporting_main_time_series_graph_number
+
+
+
+ Sales
+ sale.reporting.main.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.main,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.customer
+
+
+ sale_reporting_customer_list
+
+
+
+ sale.reporting.customer
+
+
+ sale_reporting_customer_graph_revenue
+
+
+
+ sale.reporting.customer
+
+
+ sale_reporting_customer_graph_number
+
+
+
+ Sales per Customer
+ sale.reporting.customer
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+ tree_open
+ sale.reporting.customer.category.tree,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.customer.time_series
+ tree
+ sale_reporting_main_time_series_list
+
+
+
+ sale.reporting.customer.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.customer.time_series
+ graph
+ sale_reporting_main_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.customer.category.tree
+ tree
+ children
+ sale_reporting_customer_category_tree
+
+
+
+ Sales per Customer Category
+ sale.reporting.customer.category.tree
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ sale.reporting.customer.category
+
+
+ sale_reporting_customer_category_list
+
+
+
+ Sales per Customer Category
+ sale.reporting.customer.category
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.customer.category.tree,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.customer.category.time_series
+ tree
+ sale_reporting_main_time_series_list
+
+
+
+ sale.reporting.customer.category.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.customer.category.time_series
+ graph
+ sale_reporting_main_time_series_graph_number
+
+
+
+ Sales per Party Category
+ sale.reporting.customer.category.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.customer.category,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.product
+
+
+ sale_reporting_product_list
+
+
+
+ sale.reporting.product
+
+
+ sale_reporting_product_graph_revenue
+
+
+
+ sale.reporting.product
+
+
+ sale_reporting_product_graph_number
+
+
+
+ Sales per Product
+ sale.reporting.product
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+ tree_open
+ sale.reporting.product.category.tree,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.product.time_series
+ tree
+ sale_reporting_main_time_series_list
+
+
+
+ sale.reporting.product.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.product.time_series
+ graph
+ sale_reporting_main_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.product.category.tree
+ tree
+ children
+ sale_reporting_product_category_tree
+
+
+
+ Sales per Product Category
+ sale.reporting.product.category.tree
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ sale.reporting.product.category
+
+
+ sale_reporting_product_category_list
+
+
+
+ Sales per Product Category
+ sale.reporting.product.category
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.product.category.tree,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.product.category.time_series
+ tree
+ sale_reporting_main_time_series_list
+
+
+
+ sale.reporting.product.category.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.product.category.time_series
+ graph
+ sale_reporting_main_time_series_graph_number
+
+
+
+ Sales per Product Category
+ sale.reporting.product.category.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.reporting.product.category,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.region.tree
+ tree
+ subregions
+ sale_reporting_region_tree
+
+
+
+ Sales per Region
+ sale.reporting.region.tree
+ sale.reporting.context
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ Open Region
+ sale.reporting.region.tree.open
+ sale.reporting.region.tree
+
+
+ tree_open
+ sale.reporting.region.tree,-1
+
+
+
+
+ sale.reporting.country.tree
+ tree
+ sale_reporting_country_tree
+ children
+
+
+
+ Sales per Country
+ sale.reporting.country.tree
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.reporting.country.time_series
+ tree
+ sale_reporting_main_time_series_list
+
+
+
+ sale.reporting.country.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.country.time_series
+ graph
+ sale_reporting_main_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_main_time_series_list
+
+
+
+ sale.reporting.country.subdivision.time_series
+ graph
+ sale_reporting_main_time_series_graph_revenue
+
+
+
+ sale.reporting.country.subdivision.time_series
+ graph
+ sale_reporting_main_time_series_graph_number
+
+
+
+ Sales per Subdivision
+ sale.reporting.country.subdivision.time_series
+ sale.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open Region
+ sale.reporting.country.tree.open
+ sale.reporting.country.tree
+
+
+ tree_open
+ sale.reporting.country.tree,-1
+
+
+
+
+
diff --git a/modules/sale/setup.py b/modules/sale/setup.py
new file mode 100755
index 0000000000..ff6abc5ae6
--- /dev/null
+++ b/modules/sale/setup.py
@@ -0,0 +1,155 @@
+#!/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'sparklines': ['pygal'],
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale = trytond.modules.sale
+ """,
+ )
diff --git a/modules/sale/stock.py b/modules/sale/stock.py
new file mode 100644
index 0000000000..ba210b304d
--- /dev/null
+++ b/modules/sale/stock.py
@@ -0,0 +1,213 @@
+# 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 ModelView, Workflow, fields
+from trytond.model.exceptions import AccessError
+from trytond.modules.product import round_price
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
+
+
+def process_sale(moves_field):
+ def _process_sale(func):
+ @wraps(func)
+ def wrapper(cls, shipments):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ transaction = Transaction()
+ context = transaction.context
+ 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:
+ with transaction.set_context(
+ queue_batch=context.get('queue_batch', True)):
+ 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')
+ transaction = Transaction()
+ context = transaction.context
+ 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:
+ with transaction.set_context(
+ queue_batch=context.get('queue_batch', True)):
+ Sale.__queue__.process(sales)
+ return wrapper
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+ sale = fields.Function(
+ fields.Many2One('sale.sale', "Sale"),
+ '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..4effdfa4a2
--- /dev/null
+++ b/modules/sale/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_default_methods.rst b/modules/sale/tests/scenario_sale_default_methods.rst
new file mode 100644
index 0000000000..60ed300d25
--- /dev/null
+++ b/modules/sale/tests/scenario_sale_default_methods.rst
@@ -0,0 +1,37 @@
+=============================
+Sale Default Methods Scenario
+=============================
+
+Imports::
+
+ >>> 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
+
+Activate modules::
+
+ >>> config = activate_modules('sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create a party and set their default methods::
+
+ >>> Party = Model.get('party.party')
+ >>> customer = Party(name='Customer')
+ >>> customer.sale_shipment_method = 'invoice'
+ >>> customer.sale_invoice_method = 'shipment'
+ >>> customer.save()
+
+Create a sale to to check default methods::
+
+ >>> Sale = Model.get('sale.sale')
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.shipment_method
+ 'invoice'
+ >>> sale.invoice_method
+ 'shipment'
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..6dbaaf6016
--- /dev/null
+++ b/modules/sale/tests/scenario_sale_modify_header.rst
@@ -0,0 +1,100 @@
+===========================
+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 == customer
+ True
+ >>> 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..f699ab198e
--- /dev/null
+++ b/modules/sale/tests/scenario_sale_reporting.rst
@@ -0,0 +1,323 @@
+=======================
+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::
+
+ >>> Region = Model.get('country.region')
+ >>> Country = Model.get('country.country')
+ >>> Subdivision = Model.get('country.subdivision')
+ >>> north_america, = Region.find([('code_numeric', '=', '021')])
+ >>> country_us = Country(name="United States", region=north_america)
+ >>> country_us.save()
+ >>> california = Subdivision(
+ ... name="California", type='state', country=country_us)
+ >>> california.save()
+ >>> new_york = Subdivision(
+ ... name="New York", type='state', country=country_us)
+ >>> new_york.save()
+
+Create party categories::
+
+ >>> PartyCategory = Model.get('party.category')
+ >>> party_category_root1 = PartyCategory(name="Root1")
+ >>> party_category_root1.save()
+ >>> party_category_child1 = PartyCategory(name="Child1", parent=party_category_root1)
+ >>> party_category_child1.save()
+ >>> party_category_child2 = PartyCategory(name="Child2", parent=party_category_root1)
+ >>> party_category_child2.save()
+ >>> party_category_root2 = PartyCategory(name="Root2")
+ >>> party_category_root2.save()
+
+Create parties::
+
+ >>> Party = Model.get('party.party')
+ >>> customer1 = Party(name='Customer1')
+ >>> customer1.categories.append(PartyCategory(party_category_child1.id))
+ >>> customer1.categories.append(PartyCategory(party_category_root2.id))
+ >>> address, = customer1.addresses
+ >>> address.country = country_us
+ >>> address.subdivision = california
+ >>> customer1.save()
+ >>> customer2 = Party(name='Customer2')
+ >>> customer2.categories.append(PartyCategory(party_category_child2.id))
+ >>> 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"})
+ >>> template2.account_category = account_category
+ >>> template2.save()
+ >>> 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 customer categories::
+
+ >>> CustomerCategory = Model.get('sale.reporting.customer.category')
+ >>> CustomerCategoryTimeseries = Model.get(
+ ... 'sale.reporting.customer.category.time_series')
+ >>> CustomerCategoryTree = Model.get('sale.reporting.customer.category.tree')
+ >>> with config.set_context(context=context):
+ ... reports = CustomerCategory.find([])
+ ... time_series = CustomerCategoryTimeseries.find([])
+ ... tree = CustomerCategoryTree.find([])
+ >>> len(reports)
+ 3
+ >>> with config.set_context(context=context):
+ ... sorted((r.category.id, r.number, r.revenue) for r in reports) == \
+ ... sorted([(party_category_child1.id, 1, Decimal('30')),
+ ... (party_category_root2.id, 1, Decimal('30')),
+ ... (party_category_child2.id, 1, Decimal('10'))])
+ True
+ >>> len(time_series)
+ 3
+ >>> with config.set_context(context=context):
+ ... sorted((r.category.id, r.date, r.number, r.revenue)
+ ... for r in time_series) == sorted(
+ ... [(party_category_child1.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
+ ... (party_category_root2.id, sale1.sale_date.replace(day=1), 1, Decimal('30')),
+ ... (party_category_child2.id, sale2.sale_date.replace(day=1), 1, Decimal('10'))])
+ True
+ >>> len(tree)
+ 4
+ >>> 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'))])
+ 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 product categories::
+
+ >>> ProductCategory = Model.get('sale.reporting.product.category')
+ >>> ProductCategoryTimeseries = Model.get(
+ ... 'sale.reporting.product.category.time_series')
+ >>> ProductCategoryTree = Model.get('sale.reporting.product.category.tree')
+ >>> with config.set_context(context=context):
+ ... reports = ProductCategory.find([])
+ ... time_series = ProductCategoryTimeseries.find([])
+ ... tree = ProductCategoryTree.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 countries::
+
+ >>> RegionTree = Model.get('sale.reporting.region.tree')
+ >>> CountryTree = Model.get('sale.reporting.country.tree')
+ >>> CountryTimeseries = Model.get('sale.reporting.country.time_series')
+ >>> SubdivisionTimeseries = Model.get(
+ ... 'sale.reporting.country.subdivision.time_series')
+ >>> with config.set_context(context=context):
+ ... region = RegionTree(north_america.id)
+ ... countries = CountryTree.find([])
+ ... country_time_series = CountryTimeseries.find([])
+ ... subdivision_time_series = SubdivisionTimeseries.find([])
+ >>> region.revenue == Decimal('40')
+ True
+ >>> region.parent.revenue == Decimal('40')
+ True
+ >>> len(countries)
+ 3
+ >>> with config.set_context(context=context):
+ ... sorted((c.region, c.number, c.revenue) for c in countries) == \
+ ... 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_module.py b/modules/sale/tests/test_module.py
new file mode 100644
index 0000000000..162b2dcc6b
--- /dev/null
+++ b/modules/sale/tests/test_module.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 decimal import Decimal
+
+from trytond.modules.account.tests import create_chart
+from trytond.modules.company.tests import (
+ CompanyTestMixin, PartyCompanyCheckEraseMixin, create_company, set_company)
+from trytond.pool import Pool
+from trytond.tests.test_tryton import ModuleTestCase, with_transaction
+from trytond.transaction import Transaction
+
+
+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')})
+
+
+del ModuleTestCase
diff --git a/modules/sale/tests/test_scenario.py b/modules/sale/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale/tox.ini b/modules/sale/tox.ini
new file mode 100644
index 0000000000..f16d41a030
--- /dev/null
+++ b/modules/sale/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale/* -m unittest discover -s tests
+ coverage report --include=./**/sale/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..8efde8f247
--- /dev/null
+++ b/modules/sale/tryton.cfg
@@ -0,0 +1,23 @@
+[tryton]
+version=6.7.0
+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..5e477caad0
--- /dev/null
+++ b/modules/sale/view/party_form.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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..f5f0226479
--- /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..8f03623a67
--- /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..5bd0a70d73
--- /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..2836c9272f
--- /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..cd963ded52
--- /dev/null
+++ b/modules/sale/view/sale_line_tree_sequence.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
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..966c01e35f
--- /dev/null
+++ b/modules/sale/view/sale_reporting_context_form.xml
@@ -0,0 +1,17 @@
+
+
+
diff --git a/modules/sale/view/sale_reporting_country_tree.xml b/modules/sale/view/sale_reporting_country_tree.xml
new file mode 100644
index 0000000000..b4d6b40c3b
--- /dev/null
+++ b/modules/sale/view/sale_reporting_country_tree.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_category_list.xml b/modules/sale/view/sale_reporting_customer_category_list.xml
new file mode 100644
index 0000000000..be3ad7a44f
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_category_list.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_customer_category_tree.xml b/modules/sale/view/sale_reporting_customer_category_tree.xml
new file mode 100644
index 0000000000..49afe263b1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_category_tree.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
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..bcf626b534
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_graph_number.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
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..bcf626b534
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_graph_revenue.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
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..0c2d929210
--- /dev/null
+++ b/modules/sale/view/sale_reporting_customer_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_main_graph_number.xml b/modules/sale/view/sale_reporting_main_graph_number.xml
new file mode 100644
index 0000000000..00d3cd55c1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_main_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_main_graph_revenue.xml b/modules/sale/view/sale_reporting_main_graph_revenue.xml
new file mode 100644
index 0000000000..8287682d04
--- /dev/null
+++ b/modules/sale/view/sale_reporting_main_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_main_list.xml b/modules/sale/view/sale_reporting_main_list.xml
new file mode 100644
index 0000000000..9d9fb95d31
--- /dev/null
+++ b/modules/sale/view/sale_reporting_main_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_main_time_series_graph_number.xml b/modules/sale/view/sale_reporting_main_time_series_graph_number.xml
new file mode 100644
index 0000000000..93629fd87d
--- /dev/null
+++ b/modules/sale/view/sale_reporting_main_time_series_graph_number.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_main_time_series_graph_revenue.xml b/modules/sale/view/sale_reporting_main_time_series_graph_revenue.xml
new file mode 100644
index 0000000000..19db21a4f9
--- /dev/null
+++ b/modules/sale/view/sale_reporting_main_time_series_graph_revenue.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_main_time_series_list.xml b/modules/sale/view/sale_reporting_main_time_series_list.xml
new file mode 100644
index 0000000000..d14a85bec3
--- /dev/null
+++ b/modules/sale/view/sale_reporting_main_time_series_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_category_list.xml b/modules/sale/view/sale_reporting_product_category_list.xml
new file mode 100644
index 0000000000..be3ad7a44f
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_category_list.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_reporting_product_category_tree.xml b/modules/sale/view/sale_reporting_product_category_tree.xml
new file mode 100644
index 0000000000..49afe263b1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_category_tree.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
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..41cb3fd6a1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_graph_number.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
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..41cb3fd6a1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_graph_revenue.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
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..a4dbc1c26d
--- /dev/null
+++ b/modules/sale/view/sale_reporting_product_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..49afe263b1
--- /dev/null
+++ b/modules/sale/view/sale_reporting_region_tree.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/modules/sale/view/sale_tree.xml b/modules/sale/view/sale_tree.xml
new file mode 100644
index 0000000000..a65e08bc6b
--- /dev/null
+++ b/modules/sale/view/sale_tree.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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..589dc94442
--- /dev/null
+++ b/modules/sale/view/template_tree.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_blanket_agreement/.drone.yml b/modules/sale_blanket_agreement/.drone.yml
new file mode 100644
index 0000000000..25369fb040
--- /dev/null
+++ b/modules/sale_blanket_agreement/.drone.yml
@@ -0,0 +1,76 @@
+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/*
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_blanket_agreement/.flake8 b/modules/sale_blanket_agreement/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_blanket_agreement/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_blanket_agreement/.isort.cfg b/modules/sale_blanket_agreement/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_blanket_agreement/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_blanket_agreement/CHANGELOG b/modules/sale_blanket_agreement/CHANGELOG
new file mode 100644
index 0000000000..7762ad3c72
--- /dev/null
+++ b/modules/sale_blanket_agreement/CHANGELOG
@@ -0,0 +1,3 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+Initial release
diff --git a/modules/sale_blanket_agreement/COPYRIGHT b/modules/sale_blanket_agreement/COPYRIGHT
new file mode 100644
index 0000000000..7910b5af25
--- /dev/null
+++ b/modules/sale_blanket_agreement/COPYRIGHT
@@ -0,0 +1,19 @@
+Copyright (C) 2021 Hashbang
+Copyright (C) 2021 Maxime Richez
+Copyright (C) 2021 SALUC SA
+Copyright (C) 2021 Thierry Bruyere
+Copyright (C) 2022 B2CK
+Copyright (C) 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_blanket_agreement/LICENSE b/modules/sale_blanket_agreement/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_blanket_agreement/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_blanket_agreement/MANIFEST.in b/modules/sale_blanket_agreement/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_blanket_agreement/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_blanket_agreement/README.rst b/modules/sale_blanket_agreement/README.rst
new file mode 100644
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_blanket_agreement/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_blanket_agreement/__init__.py b/modules/sale_blanket_agreement/__init__.py
new file mode 100644
index 0000000000..58c232074d
--- /dev/null
+++ b/modules/sale_blanket_agreement/__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
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Configuration,
+ sale.ConfigurationSequence,
+ sale.BlanketAgreement,
+ sale.BlanketAgreementLine,
+ sale.Sale,
+ sale.Line,
+ sale.BlanketAgreementCreateSaleStart,
+ module='sale_blanket_agreement', type_='model')
+ Pool.register(
+ sale.BlanketAgreementCreateSale,
+ module='sale_blanket_agreement', type_='wizard')
diff --git a/modules/sale_blanket_agreement/doc/conf.py b/modules/sale_blanket_agreement/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_blanket_agreement/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_blanket_agreement/doc/design.rst b/modules/sale_blanket_agreement/doc/design.rst
new file mode 100644
index 0000000000..891ed6d23d
--- /dev/null
+++ b/modules/sale_blanket_agreement/doc/design.rst
@@ -0,0 +1,49 @@
+******
+Design
+******
+
+The *Sale Blanket Agreement Module* introduces the following concepts:
+
+.. _model-sale.blanket_agreement:
+
+Sale Blanket Agreement
+======================
+
+The *Sale Blanket Agreement* is used to manage the agreements between
+the company and its customers.
+
+Each agreement progresses through multiple states: 'draft' as default when
+created, 'running' when operational then 'done' or 'cancelled' as final step.
+A warning is displayed if the user tries to close an agreement with remaining
+quantities.
+
+An agreement is identified by a unique number that is generated automatically
+from the configured *Sequence* and may also have other general information such
+a validity period, a description, or a reference provided by the customer.
+
+Each agreement is made up from one or more lines.
+Each line on an agreement provides information about which `Products
+`, the price, the agreed quantity, the processed
+quantity and the remaining quantity.
+
+.. seealso::
+
+ Sale Blanket Agreements can be found by opening the main menu item:
+
+ |Sales --> Blanket Agreements|__ menu item.
+
+ .. |Sales --> Blanket Agreements| replace:: :menuselection:`Sales --> Blanket Agreements`
+ __ https://demo.tryton.org/model/sale.blanket_agreement
+
+Wizard
+------
+
+.. _wizard-sale.blanket_agreement.create_sale_wizard:
+
+Create Sale
+^^^^^^^^^^^
+
+The *Create Sale* wizard helps the user to create a sale from an blanket
+agreement.
+A specific form allows the user to select the blanket agreement lines that will
+compose the sale with their remaining quantities.
diff --git a/modules/sale_blanket_agreement/doc/index.rst b/modules/sale_blanket_agreement/doc/index.rst
new file mode 100644
index 0000000000..ff38479658
--- /dev/null
+++ b/modules/sale_blanket_agreement/doc/index.rst
@@ -0,0 +1,12 @@
+#############################
+Sale Blanket Agreement Module
+#############################
+
+The *Sale Blanket Agreement Module* manages long-term contracts with customers
+to sell a specific quantity of products with multiple orders over a period.
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ releases
diff --git a/modules/sale_blanket_agreement/doc/releases.rst b/modules/sale_blanket_agreement/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_blanket_agreement/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_blanket_agreement/exceptions.py b/modules/sale_blanket_agreement/exceptions.py
new file mode 100644
index 0000000000..1e16c809e0
--- /dev/null
+++ b/modules/sale_blanket_agreement/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 UserWarning
+
+
+class BlanketAgreementQuantityWarning(UserWarning):
+ pass
+
+
+class BlanketAgreementClosingWarning(UserWarning):
+ pass
diff --git a/modules/sale_blanket_agreement/locale/bg.po b/modules/sale_blanket_agreement/locale/bg.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/bg.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/ca.po b/modules/sale_blanket_agreement/locale/ca.po
new file mode 100644
index 0000000000..3546ee5591
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/ca.po
@@ -0,0 +1,265 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr "Descripció"
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr "Des de la data"
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr "Referència"
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr "Fins a la data"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr "Acord"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr "Estat acord"
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr "Acord general"
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr "Quantitat procesada"
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr "Categoria UdM del producte"
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr "Quantitat restant"
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr "Línies de venda"
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Seqüència acord general"
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Seqüència acord general"
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr "Línia d'acord general"
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr "Acords generals"
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Acords generals"
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr "Vendes"
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr "Línies de venda"
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr "Crea una venda"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr "En execució"
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+"El acord \"%(agreement)s\" que es vol tancar encara té quantitats pendents."
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+"Per canviar l'unitat de la línia d'acord \"%(line)s\", heu d'escollir una "
+"compatible amb les línies de venda existents."
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+"La quantitat de la línia \"%(line)s\" es superior a la quantitat restant "
+"(%remaining)s\" de l'acord \"%(agreement)s\"."
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr "Tanca"
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr "Crea una venda"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr "Executa"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr "Acords generals de venda"
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Acord general de venda"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Acord general de venda"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Acords generals"
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Acord general de venda"
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr "Acord general de venda"
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr "Crea venda"
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr "Línia d'acord general de venda"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr "Cancel·lat"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr "Tancat"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr "En execució"
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr "Acord"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr "Informació addicional"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr "Crea"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
diff --git a/modules/sale_blanket_agreement/locale/cs.po b/modules/sale_blanket_agreement/locale/cs.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/cs.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/de.po b/modules/sale_blanket_agreement/locale/de.po
new file mode 100644
index 0000000000..897d61934a
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/de.po
@@ -0,0 +1,267 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr "Kunde"
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr "Von Datum"
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr "Referenz"
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr "Bis Datum"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr "Rahmenvertrag"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr "Rahmenvertragsstatus"
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr "Rahmenvertrag"
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr "Abgerufene Menge"
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr "Maßeinheitenkategorie"
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr "Verbleibende Menge"
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr "Verkaufspositionen"
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr "Maßeinheit"
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Nummernkreis Rahmenvertrag"
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Nummernkreis Rahmenvertrag"
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr "Rahmenvertragsposition"
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr "Rahmenverträge"
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Rahmenverträge"
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr "Verkäufe"
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr "Verkaufspositionen"
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr "Verkauf Erstellen"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr "In Ausführung"
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+"Der zu schließende Rahmenvertrag \"%(agreement)s\" verfügt noch über "
+"Restmengen."
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+"Um die Maßeinheit der Rahmenvertragsposition \"%(line)s\" zu ändern, müssen "
+"Sie eine auswählen, die mit den vorhandenen Verkaufspositionen kompatibel "
+"ist."
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+"Die Menge der Position \"%(line)s\" ist größer als die verbleibende Menge "
+"(%(remaining)s) des Rahmenvertrags \"%(agreement)s\"."
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr "Annullieren"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr "Beenden"
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr "Verkauf Erstellen"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr "Ausführen"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr "Verkaufsrahmenvertrag"
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Verkaufsrahmenvertrag"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Verkaufsrahmenvertrag"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Rahmenverträge"
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Verkaufsrahmenvertrag"
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr "Verkaufsrahmenvertrag"
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr "Verkauf Erstellen"
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr "Verkaufsrahmenvertragsposition"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr "Beendet"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr "In Ausführung"
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr "Allgemein"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr "Vertragliches"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr "Sonstiges"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr "Erstellen"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
diff --git a/modules/sale_blanket_agreement/locale/es.po b/modules/sale_blanket_agreement/locale/es.po
new file mode 100644
index 0000000000..296b7f8762
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/es.po
@@ -0,0 +1,266 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr "Cliente"
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr "Descripción"
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr "Desde la fecha"
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr "Referencia"
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr "Hasta la fecha"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr "Acuerdo"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr "Estado acuerdo"
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr "Acuerdo general"
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr "Cantidad procesada"
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr "Categoría UdM del producto"
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr "Cantidad restante"
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr "Líneas de venta"
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Sequencia acuerdo general"
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Sequencia acuerdo general"
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr "Linea de acuerdo general"
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr "Acuerdos generales"
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Acuerdos generales"
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr "Ventas"
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr "Líneas de venta"
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr "Crear una venta"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr "En ejecución"
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+"El acuerdo \"%(agreement)s\" que se quiere cerrar todavia tiene cantidades "
+"pendientes."
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+"Para cambiar la unidad de la linea de acuerdo \"%(line)s\", tenéis que "
+"seleccionar una comptabile con las lineas de compra existentes."
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+"La cantidad de la linea \"%(line)s\" es mas grande que la cantidad restante "
+"(%(remaining)s) del acuerdo \"%(agreement)s\"."
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr "Cerrar"
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr "Crear una venta"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr "Ejecutar"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr "Acuerdos generales de ventas"
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Acuerdo general de ventas"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Acuerdo general de ventas"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Acuerdos generales"
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Acuerdo general de ventas"
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr "Acuerdo general de ventas"
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr "Crear venta"
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr "Linea de acuerdo general de ventas"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr "Cancelado"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr "Cerrado"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr "En ejecución"
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr "Acuerdo"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr "Información adicional"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr "Crear"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr "Cancelar"
diff --git a/modules/sale_blanket_agreement/locale/es_419.po b/modules/sale_blanket_agreement/locale/es_419.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/es_419.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/et.po b/modules/sale_blanket_agreement/locale/et.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/et.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/fa.po b/modules/sale_blanket_agreement/locale/fa.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/fa.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/fi.po b/modules/sale_blanket_agreement/locale/fi.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/fi.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/fr.po b/modules/sale_blanket_agreement/locale/fr.po
new file mode 100644
index 0000000000..f4554895c5
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/fr.po
@@ -0,0 +1,265 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr "Référence"
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr "Contrat"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr "État du contrat"
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr "Contrat-cadre"
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr "Quantité traitée"
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr "Catégorie d'UdM de produit"
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr "Quantité restante"
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr "Lignes de vente"
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Séquence de contrat-cadre"
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Séquence de contrat-cadre"
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr "Ligne de contrat-cadre"
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr "Contrats-cadres"
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Contrats-cadres"
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr "Ventes"
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr "Lignes de vente"
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr "Créer une vente"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr "Tous"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr "En cours"
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+"Le contrat « %(agreement)s » à clôturer a encore des quantités restantes."
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+"Pour changer l'unité de la ligne contrat « %(line)s », vous devez en choisir"
+" une compatible avec les lignes de vente existantes."
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+"La quantité de la ligne « %(line)s » est supérieure à la quantité restante "
+"(%(remaining)s) du contrat « %(agreement)s »."
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr "Clôturer"
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr "Créer une vente"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr "Lancer"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr "Contrat-cadre de ventes"
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Contrat-cadre de vente"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Contrat-cadre de vente"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Contrats-cadres"
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Contrat-cadre de vente"
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr "Contrat-cadre de vente"
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr "Créer une vente"
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr "Ligne de contrat-cadre de vente"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr "Annulés"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr "Clôturés"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr "En cours"
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr "Général"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr "Contrat"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr "Autre information"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr "Créer"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr "Annuler"
diff --git a/modules/sale_blanket_agreement/locale/hu.po b/modules/sale_blanket_agreement/locale/hu.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/hu.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/id.po b/modules/sale_blanket_agreement/locale/id.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/id.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/it.po b/modules/sale_blanket_agreement/locale/it.po
new file mode 100644
index 0000000000..47a639d9da
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/it.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr "Prodotto"
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr "Quantità"
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr "Annullato"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/lo.po b/modules/sale_blanket_agreement/locale/lo.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/lo.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/lt.po b/modules/sale_blanket_agreement/locale/lt.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/lt.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/nl.po b/modules/sale_blanket_agreement/locale/nl.po
new file mode 100644
index 0000000000..ffae117574
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/nl.po
@@ -0,0 +1,266 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr "Klant"
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr "Omschrijving"
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr "Vanaf datum"
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr "Referentie"
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr "Tot datum"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr "Overeenkomst"
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr "Status overeenkomst"
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr "Algemene overeenkomst"
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr "Verwerkte hoeveelheid"
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr "Categorie product maateenheid"
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr "Resterende hoeveelheid"
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr "Verkoop regels"
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheidsprijs"
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Algemene overeenkomst reeks"
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr "Algemene overeenkomst reeks"
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr "Algemene overeenkomst regel"
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr "Algemene overeenkomsten"
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Algemene overeenkomsten"
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr "Verkoop"
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr "Verkoop Regels"
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr "Verkooporder maken"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr "Alles"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr "In uitvoering"
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+"De af te ronden overeenkomst \"%(agreement)s\" heeft nog resterende "
+"hoeveelheden."
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+"Om de eenheid van de overeenkomst regel \"%(line)s\" te wijzigen, moet u een"
+" eenheid kiezen die aansluit bij de bestaande verkoop regels."
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+"De hoeveelheid van regel \"%(line)s\" is groter dan de resterende "
+"hoeveelheid (%(remaining)s) van overeenkomst \"%(agreement)s\"."
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr "Afronden"
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr "Verkooporder maken"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr "Uitvoeren"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr "Algemene verkoopovereenkomsten"
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Algemene verkoopovereenkomst"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Algemene verkoopovereenkomst"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr "Algemene overeenkomsten"
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr "Algemene verkoopovereenkomst"
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr "Algemene verkoopovereenkomst"
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr "Verkooporder maken"
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr "Algemene verkoopovereenkomst regel"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr "Afgerond"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr "In uitvoering"
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr "Algemeen"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr "Overeenkomst"
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr "Overige informatie"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr "Aanmaken"
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr "Annuleer"
diff --git a/modules/sale_blanket_agreement/locale/pl.po b/modules/sale_blanket_agreement/locale/pl.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/pl.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/pt.po b/modules/sale_blanket_agreement/locale/pt.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/pt.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/ro.po b/modules/sale_blanket_agreement/locale/ro.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/ro.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/ru.po b/modules/sale_blanket_agreement/locale/ru.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/ru.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/sl.po b/modules/sale_blanket_agreement/locale/sl.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/sl.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/tr.po b/modules/sale_blanket_agreement/locale/tr.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/tr.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/uk.po b/modules/sale_blanket_agreement/locale/uk.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/uk.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/locale/zh_CN.po b/modules/sale_blanket_agreement/locale/zh_CN.po
new file mode 100644
index 0000000000..207246bf79
--- /dev/null
+++ b/modules/sale_blanket_agreement/locale/zh_CN.po
@@ -0,0 +1,260 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.blanket_agreement,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,customer:"
+msgid "Customer"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,description:"
+msgid "Description"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,reference:"
+msgid "Reference"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.create_sale.start,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,agreement_state:"
+msgid "Agreement State"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,blanket_agreement:"
+msgid "Blanket Agreement"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,processed_quantity:"
+msgid "Processed quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,product_uom_category:"
+msgid "Product UOM Category"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,remaining_quantity:"
+msgid "Remaining quantity"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,sale_lines:"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.blanket_agreement.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "field:sale.configuration,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.configuration.sequence,blanket_agreement_sequence:"
+msgid "Blanket Agreement Sequence"
+msgstr ""
+
+msgctxt "field:sale.line,blanket_agreement_line:"
+msgid "Blanket Agreement Line"
+msgstr ""
+
+msgctxt "field:sale.sale,blanket_agreements:"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form_blanket_agreement"
+msgid "Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_line_form_blanket_agreement"
+msgid "Sale Lines"
+msgstr ""
+
+msgctxt "model:ir.action,name:sale_blanket_agreement_create_sale_wizard"
+msgid "Create a Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_draft"
+msgid "Draft"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_sale_blanket_agreement_domain_running"
+msgid "Running"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_closed_remaining_quantity"
+msgid ""
+"The agreement \"%(agreement)s\" to be closed has still remaining quantities."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_agreement_line_incompatible_unit"
+msgid ""
+"To change the unit of agreement line \"%(line)s\", you must choose one "
+"compatible with the existing sale lines."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_quantity_greater_remaining"
+msgid ""
+"The quantity of line \"%(line)s\" is greater than the remaining quantity "
+"(%(remaining)s) of agreement \"%(agreement)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt ""
+"model:ir.model.button,string:sale_blanket_agreement_create_sale_button"
+msgid "Create a sale"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_draft_button"
+msgid "Draft"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_blanket_agreement_run_button"
+msgid "Run"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_blanket_agreement_companies"
+msgid "Sales Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence,name:sequence_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.sequence.type,name:sequence_type_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_blanket_agreement"
+msgid "Blanket Agreements"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_blanket_agreement"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement,name:"
+msgid "Sale Blanket Agreement"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.create_sale.start,name:"
+msgid "Create Sale"
+msgstr ""
+
+msgctxt "model:sale.blanket_agreement.line,name:"
+msgid "Sale Blanket Agreement Line"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.blanket_agreement,state:"
+msgid "Running"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Agreement"
+msgstr ""
+
+msgctxt "view:sale.blanket_agreement:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,create_sale:"
+msgid "Create"
+msgstr ""
+
+msgctxt "wizard_button:sale.blanket_agreement.create_sale,start,end:"
+msgid "Cancel"
+msgstr ""
diff --git a/modules/sale_blanket_agreement/message.xml b/modules/sale_blanket_agreement/message.xml
new file mode 100644
index 0000000000..f75fc3c2ab
--- /dev/null
+++ b/modules/sale_blanket_agreement/message.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ The agreement "%(agreement)s" to be closed has still remaining quantities.
+
+
+ The quantity of line "%(line)s" is greater than the remaining quantity (%(remaining)s) of agreement "%(agreement)s".
+
+
+ To change the unit of agreement line "%(line)s", you must choose one compatible with the existing sale lines.
+
+
+
diff --git a/modules/sale_blanket_agreement/product.xml b/modules/sale_blanket_agreement/product.xml
new file mode 100644
index 0000000000..21007c556f
--- /dev/null
+++ b/modules/sale_blanket_agreement/product.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ product.product
+ tree
+
+ product_list_agreement_line
+
+
+
diff --git a/modules/sale_blanket_agreement/sale.py b/modules/sale_blanket_agreement/sale.py
new file mode 100644
index 0000000000..78a086550b
--- /dev/null
+++ b/modules/sale_blanket_agreement/sale.py
@@ -0,0 +1,794 @@
+# 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 itertools import groupby
+
+from trytond.i18n import gettext
+from trytond.model import Index, ModelSQL, ModelView, Workflow, fields
+from trytond.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits, round_price
+from trytond.modules.product.exceptions import UOMValidationError
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Bool, Date, Eval, Id, If
+from trytond.transaction import Transaction
+from trytond.wizard import Button, StateAction, StateView, Wizard
+
+from .exceptions import (
+ BlanketAgreementClosingWarning, BlanketAgreementQuantityWarning)
+
+
+def blanket_agreement_quantity_warning():
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(cls, sales, *args, **kwargs):
+ pool = Pool()
+ Warning = pool.get('res.user.warning')
+ Lang = pool.get('ir.lang')
+ for sale in sales:
+ for line in sale.lines:
+ agreement_line = line.blanket_agreement_line
+ if not agreement_line:
+ continue
+ remaining_quantity = (
+ agreement_line.remainig_quantity_for_sale(line))
+ if (remaining_quantity is not None
+ and line.quantity > remaining_quantity):
+ warning_key = Warning.format(
+ 'blanket_agreement_quantity_greater_remaining',
+ [line])
+ if Warning.check(warning_key):
+ lang = Lang.get()
+ raise BlanketAgreementQuantityWarning(
+ warning_key,
+ gettext('sale_blanket_agreement'
+ '.msg_quantity_greater_remaining',
+ line=line.rec_name,
+ remaining=lang.format_number_symbol(
+ remaining_quantity, line.unit),
+ agreement=agreement_line.rec_name))
+ return func(cls, sales, *args, **kwargs)
+ return wrapper
+ return decorator
+
+
+class Configuration(metaclass=PoolMeta):
+ "Sale Configuration"
+ __name__ = 'sale.configuration'
+
+ blanket_agreement_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Blanket Agreement Sequence",
+ required=True,
+ domain=[
+ ('company', 'in',
+ [Eval('context', {}).get('company', -1), None]),
+ ('sequence_type', '=',
+ Id('sale_blanket_agreement',
+ 'sequence_type_blanket_agreement')),
+ ]))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'blanket_agreement_sequence':
+ return pool.get('sale.configuration.sequence')
+ return super().multivalue_model(field)
+
+ @classmethod
+ def default_blanket_agreement_sequence(cls, **pattern):
+ return cls.multivalue_model(
+ 'blanket_agreement_sequence'
+ ).default_blanket_agreement_sequence()
+
+
+class ConfigurationSequence(metaclass=PoolMeta):
+ "Sale Configuration Sequence"
+ __name__ = 'sale.configuration.sequence'
+ blanket_agreement_sequence = fields.Many2One(
+ 'ir.sequence', "Blanket Agreement Sequence", required=True,
+ domain=[
+ ('company', 'in', [Eval('company', -1), None]),
+ ('sequence_type', '=',
+ Id('sale_blanket_agreement',
+ 'sequence_type_blanket_agreement')),
+ ])
+
+ @classmethod
+ def default_blanket_agreement_sequence(cls):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ try:
+ return ModelData.get_id(
+ 'sale_blanket_agreement', 'sequence_blanket_agreement')
+ except KeyError:
+ return None
+
+
+class BlanketAgreement(Workflow, ModelSQL, ModelView):
+ "Sale Blanket Agreement"
+ __name__ = 'sale.blanket_agreement'
+ _rec_name = 'number'
+
+ company = fields.Many2One(
+ 'company.company', "Company", required=True,
+ states={
+ 'readonly': (
+ (Eval('state') != 'draft')
+ | Eval('lines', [0])
+ | Eval('customer', True)),
+ })
+ number = fields.Char("Number", readonly=True)
+ reference = fields.Char("Reference")
+ description = fields.Char(
+ "Description",
+ states={
+ 'readonly': Eval('state') != 'draft',
+ })
+ customer = fields.Many2One(
+ 'party.party', "Customer", required=True,
+ states={
+ 'readonly': (
+ (Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('customer'))),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends=['company'])
+ from_date = fields.Date(
+ "From Date",
+ domain=[
+ If(Eval('to_date') & Eval('from_date'),
+ ('from_date', '<=', Eval('to_date')),
+ ()),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ 'required': ~Eval('state').in_(['draft', 'cancelled']),
+ })
+ to_date = fields.Date(
+ "To Date",
+ domain=[
+ If(Eval('from_date') & Eval('to_date'),
+ ('to_date', '>=', Eval('from_date')),
+ ()),
+ ],
+ states={
+ 'readonly': ~Eval('state').in_(['draft', 'running']),
+ 'required': Eval('state') == 'closed',
+ })
+ currency = fields.Many2One(
+ 'currency.currency', "Currency", required=True,
+ states={
+ 'readonly': (
+ (Eval('state') != 'draft')
+ | (Eval('lines', [0]) & Eval('currency', 0))),
+ })
+ lines = fields.One2Many(
+ 'sale.blanket_agreement.line', 'blanket_agreement', "Lines",
+ states={
+ 'readonly': (
+ (Eval('state') != 'draft')
+ | ~Eval('customer'))
+ })
+
+ amount = fields.Function(Monetary(
+ "Amount", currency='currency', digits='currency'),
+ 'on_change_with_amount')
+
+ state = fields.Selection([
+ ('draft', "Draft"),
+ ('running', "Running"),
+ ('closed', "Closed"),
+ ('cancelled', "Cancelled"),
+ ], "State", readonly=True, required=True)
+
+ @classmethod
+ def __setup__(cls):
+ cls.number.search_unaccented = False
+ cls.reference.search_unaccented = False
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.update({
+ Index(t, (t.reference, Index.Similarity())),
+ Index(
+ t, (t.state, Index.Equality()),
+ where=t.state.in_(['draft', 'running'])),
+ })
+
+ cls._order = [
+ ('from_date', 'DESC NULLS FIRST'),
+ ('id', 'DESC'),
+ ]
+ cls._transitions |= set((
+ ('draft', 'running'),
+ ('draft', 'cancelled'),
+ ('running', 'draft'),
+ ('running', 'closed'),
+ ('closed', 'running'),
+ ('cancelled', 'draft'),
+ ))
+ cls._buttons.update({
+ 'cancel': {
+ 'invisible': Eval('state') != 'draft',
+ 'depends': ['state'],
+ },
+ 'draft': {
+ 'invisible': ~Eval('state').in_(['cancelled', 'running']),
+ 'icon': 'tryton-undo',
+ 'depends': ['state'],
+ },
+ 'run': {
+ 'invisible': (
+ (Eval('state') != 'draft')
+ & ~(Id('sale', 'group_sale_admin').in_(
+ Eval('context', {}).get('groups', []))
+ & (Eval('state') == 'closed'))),
+ 'readonly': (~Eval('lines')
+ | (Eval('from_date', Date()) > Date())),
+ 'icon': If(Eval('state') == 'closed',
+ 'tryton-back',
+ 'tryton-forward'),
+ 'depends': ['state'],
+ },
+ 'create_sale': {
+ 'invisible': Eval('state') != 'running',
+ 'depends': ['state'],
+ },
+ 'close': {
+ 'invisible': Eval('state') != 'running',
+ 'depends': ['state'],
+ },
+ })
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_currency(cls, **pattern):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = pattern.get('company')
+ if not company:
+ company = cls.default_company()
+ if company:
+ return Company(company).currency.id
+
+ @fields.depends('company', 'customer', 'lines')
+ def on_change_customer(self):
+ if not self.lines:
+ self.currency = self.default_currency(
+ company=self.company.id if self.company else None)
+ if self.customer and self.customer.customer_currency:
+ self.currency = self.customer.customer_currency
+
+ @fields.depends('lines', 'currency')
+ def on_change_with_amount(self, name=None):
+ amount = sum(
+ (line.amount or Decimal(0) for line in self.lines),
+ Decimal(0))
+ if self.currency:
+ amount = self.currency.round(amount)
+ return amount
+
+ @classmethod
+ def default_state(cls):
+ return 'draft'
+
+ @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'
+
+ return [bool_op,
+ ('number', operator, value),
+ ('reference', operator, value),
+ ]
+
+ @classmethod
+ def copy(cls, agreements, default=None):
+ default = default.copy() if default is not None else {}
+ default.setdefault('number', None)
+ default.setdefault('from_date', None)
+ default.setdefault('to_date', None)
+ return super().copy(agreements, default=default)
+
+ @classmethod
+ def set_number(cls, agreements):
+ '''
+ Fill the number field with the blanket agreement sequence
+ '''
+ pool = Pool()
+ Config = pool.get('sale.configuration')
+
+ config = Config(1)
+ for agreement in agreements:
+ if agreement.number:
+ continue
+ agreement.number = config.get_multivalue(
+ 'blanket_agreement_sequence',
+ company=agreement.company.id).get()
+ cls.save(agreements)
+
+ @classmethod
+ def set_date(cls, agreements, field):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ for company, agreements in groupby(
+ agreements, key=lambda p: p.company):
+ with Transaction().set_context(company=company.id):
+ today = Date.today()
+ cls.write([a for a in agreements if not getattr(a, field)], {
+ field: today,
+ })
+
+ @classmethod
+ def view_attributes(cls):
+ return super().view_attributes() + [
+ ('/tree', 'visual',
+ If(Eval('state').in_(['cancelled', 'closed']),
+ 'muted',
+ If(Eval('to_date', Date()) < Date(),
+ 'warning',
+ ''))),
+ ]
+
+ def get_sale(self, lines=None):
+ pool = Pool()
+ Sale = pool.get('sale.sale')
+ sale = Sale(
+ company=self.company,
+ party=self.customer,
+ )
+ sale.on_change_party()
+ self.currency = self.currency
+ if lines:
+ sale_lines = []
+ for line in lines:
+ assert line.blanket_agreement == self
+ sale_line = line.get_sale_line(sale)
+ sale_lines.append(sale_line)
+ sale.lines = sale_lines
+ return sale
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, agreements):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, agreements):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('running')
+ def run(cls, agreements):
+ cls.set_number(agreements)
+ cls.set_date(agreements, 'from_date')
+
+ @classmethod
+ @ModelView.button_action(
+ 'sale_blanket_agreement'
+ '.sale_blanket_agreement_create_sale_wizard')
+ def create_sale(cls, agreements):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('closed')
+ def close(cls, agreements):
+ pool = Pool()
+ Warning = pool.get('res.user.warning')
+ Date = pool.get('ir.date')
+ today = Date.today()
+ cls.set_date(agreements, 'to_date')
+ for agreement in agreements:
+ if agreement.to_date > today:
+ if any(l.remaining_quantity > 0 for l in agreement.lines):
+ warning_key = Warning.format(
+ 'closed_remaining_quantity', [agreement])
+ if Warning.check(warning_key):
+ raise BlanketAgreementClosingWarning(
+ warning_key,
+ gettext('sale_blanket_agreement'
+ '.msg_agreement_closed_remaining_quantity',
+ agreement=agreement.rec_name))
+
+
+class BlanketAgreementLine(ModelSQL, ModelView):
+ "Sale Blanket Agreement Line"
+ __name__ = 'sale.blanket_agreement.line'
+
+ _states = {
+ 'readonly': Eval('agreement_state') != 'draft'
+ }
+
+ blanket_agreement = fields.Many2One(
+ 'sale.blanket_agreement', "Blanket Agreement",
+ ondelete='CASCADE', required=True,
+ states={
+ 'readonly': (
+ _states['readonly'] & Bool(Eval('blanket_agreement'))),
+ })
+ product = fields.Many2One(
+ 'product.product', "Product", ondelete='RESTRICT', required=True,
+ domain=[
+ If(Eval('agreement_state') == 'draft',
+ ('salable', '=', True),
+ ()),
+ ],
+ states=_states,
+ context={
+ 'company': Eval('company', None),
+ },
+ search_context={
+ 'currency': Eval('_parent_agreement', {}).get('currency'),
+ 'customer': Eval('_parent_agreement', {}).get('customer'),
+ 'quantity': Eval('quantity'),
+ 'uom': Eval('unit'),
+ },
+ depends=['company', 'unit', 'quantity'])
+ product_uom_category = fields.Function(
+ fields.Many2One('product.uom.category', "Product UOM Category"),
+ 'on_change_with_product_uom_category')
+ quantity = fields.Float("Quantity", digits='unit', states=_states)
+ unit = fields.Many2One(
+ 'product.uom', "Unit", ondelete='RESTRICT', required=True,
+ states=_states)
+ unit_price = Monetary(
+ "Unit Price", digits=price_digits, currency='currency', required=True,
+ states=_states)
+ amount = fields.Function(
+ Monetary("Amount", digits='currency', currency='currency'),
+ 'on_change_with_amount')
+ processed_quantity = fields.Function(
+ fields.Float("Processed quantity", digits='unit'),
+ 'get_processed_quantity')
+ remaining_quantity = fields.Function(
+ fields.Float(
+ "Remaining quantity", digits='unit',
+ states={
+ 'invisible': ~Eval('quantity'),
+ }),
+ 'on_change_with_remaining_quantity')
+ sale_lines = fields.One2Many(
+ 'sale.line', 'blanket_agreement_line', "Sale Lines", readonly=True)
+
+ agreement_state = fields.Function(
+ fields.Selection(
+ 'get_sale_blanket_agreement_states', "Agreement State"),
+ 'on_change_with_agreement_state')
+ company = fields.Function(
+ fields.Many2One('company.company', "Company"),
+ 'on_change_with_company')
+ currency = fields.Function(
+ fields.Many2One('currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ del _states
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('blanket_agreement')
+ unit_categories = cls._unit_categories()
+ cls.unit.domain = [
+ If(Bool(Eval('product_uom_category')),
+ ('category', 'in', [Eval(c) for c in unit_categories]),
+ ('category', '!=', -1)),
+ ]
+
+ @fields.depends(
+ 'product', 'unit', 'blanket_agreement',
+ '_parent_blanket_agreement.customer',
+ methods=['on_change_with_amount'])
+ 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
+
+ @classmethod
+ def _unit_categories(cls):
+ return ['product_uom_category']
+
+ @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(
+ 'quantity', 'unit_price', 'blanket_agreement',
+ '_parent_blanket_agreement.currency')
+ def on_change_with_amount(self, name=None):
+ amount = (
+ Decimal(str(self.quantity or '0.0'))
+ * (self.unit_price or Decimal('0.0')))
+
+ if self.blanket_agreement and self.blanket_agreement.currency:
+ return self.blanket_agreement.currency.round(amount)
+ return amount
+
+ @fields.depends('blanket_agreement', '_parent_blanket_agreement.currency')
+ def on_change_with_currency(self, name=None):
+ if self.blanket_agreement and self.blanket_agreement.currency:
+ return self.blanket_agreement.currency.id
+
+ def get_processed_quantity(self, name=None):
+ processed_quantity = 0.
+ for line in self.sale_lines:
+ if line.sale.state in {'confirmed', 'processing', 'done'}:
+ processed_quantity += line.quantity_for_blanket_agreement(
+ self, round=False)
+ return self.unit.round(processed_quantity)
+
+ @fields.depends('quantity', 'processed_quantity')
+ def on_change_with_remaining_quantity(self, name=None):
+ if self.quantity is not None:
+ return max(self.quantity - (self.processed_quantity or 0.), 0.)
+
+ @classmethod
+ def get_sale_blanket_agreement_states(cls):
+ pool = Pool()
+ Agreement = pool.get('sale.blanket_agreement')
+ return Agreement.fields_get(['state'])['state']['selection']
+
+ @fields.depends('blanket_agreement', '_parent_blanket_agreement.state')
+ def on_change_with_agreement_state(self, name=None):
+ if self.blanket_agreement:
+ return self.blanket_agreement.state
+
+ @fields.depends('blanket_agreement', '_parent_blanket_agreement.company')
+ def on_change_with_company(self, name=None):
+ if self.blanket_agreement and self.blanket_agreement.company:
+ return self.blanket_agreement.company.id
+
+ def get_sale_line(self, sale):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ sale_line = SaleLine(
+ sale=sale,
+ product=self.product,
+ blanket_agreement_line=self,
+ )
+ sale_line.on_change_product()
+ self._set_sale_line_quantity(sale_line)
+ return sale_line
+
+ def _set_sale_line_quantity(self, sale_line):
+ if self.unit.category == self.product.sale_uom.category:
+ sale_line.quantity = self.remaining_quantity or 0
+ sale_line.unit = self.unit
+ sale_line.unit_price = self.unit_price
+ sale_line.on_change_quantity()
+
+ def get_rec_name(self, name):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ lang = Lang.get()
+ name = f'{self.product.rec_name}s @ {self.blanket_agreement.rec_name}'
+ if self.quantity is not None:
+ name = '%s %s' % (lang.format_number_symbol(
+ self.quantity, self.unit, digits=self.unit.digits), name)
+ return name
+
+ @classmethod
+ def validate_fields(cls, records, field_names):
+ super().validate_fields(records, field_names)
+ cls.check_unit(records, field_names)
+
+ @classmethod
+ def check_unit(cls, lines, field_names=None):
+ if field_names and not (field_names & {'unit'}):
+ return
+ for line in lines:
+ for sale_line in line.sale_lines:
+ if not line.is_same_uom_category(sale_line):
+ raise UOMValidationError(
+ gettext('sale_blanket_agreement'
+ '.msg_agreement_line_incompatible_unit',
+ line=line.rec_name))
+
+ def is_same_uom_category(self, sale_line):
+ return self.unit.category == sale_line.product_uom_category
+
+ def remainig_quantity_for_sale(self, line, round=True):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if (self.remaining_quantity is not None
+ and self.unit.category == line.unit.category):
+ return Uom.compute_qty(
+ self.unit, self.remaining_quantity, line.unit,
+ round=round)
+
+ @classmethod
+ def copy(cls, lines, default=None):
+ default = default.copy() if default is not None else {}
+ default.setdefault('sale_lines', None)
+ return super().copy(lines, default=default)
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ blanket_agreements = fields.Function(fields.Many2Many(
+ 'sale.blanket_agreement', None, None, "Blanket Agreements"),
+ 'get_blanket_agreements', searcher='search_blanket_agreements')
+
+ def get_blanket_agreements(self, name):
+ return list({
+ l.blanket_agreement_line.blanket_agreement.id
+ for l in self.lines
+ if l.blanket_agreement_line})
+
+ @classmethod
+ def search_blanket_agreements(cls, name, clause):
+ return [
+ ('lines.blanket_agreement_line.blanket_agreement'
+ + clause[0][len(name):], *clause[1:])]
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('quotation')
+ @blanket_agreement_quantity_warning()
+ def quote(cls, sales):
+ super().quote(sales)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('confirmed')
+ @blanket_agreement_quantity_warning()
+ def confirm(cls, sales):
+ super().confirm(sales)
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ blanket_agreement_line = fields.Many2One(
+ 'sale.blanket_agreement.line', "Blanket Agreement Line",
+ ondelete='RESTRICT',
+ states={
+ 'invisible': ~Eval('product'),
+ 'readonly': Eval('sale_state') != 'draft',
+ })
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ sale_date = Eval('_parent_sale', {}).get(
+ 'sale_date', Date())
+ sale_date = If(sale_date, sale_date, Date())
+ cls.blanket_agreement_line.domain = [
+ If(Eval('sale_state').in_(['draft', 'quotation']),
+ [
+ ('blanket_agreement.state', '=', 'running'),
+ ['OR',
+ ('blanket_agreement.from_date', '<=', sale_date),
+ ('blanket_agreement.from_date', '=', None),
+ ],
+ ['OR',
+ ('blanket_agreement.to_date', '>=', sale_date),
+ ('blanket_agreement.to_date', '=', None),
+ ],
+ cls._domain_blanket_agreemnt_line_product(),
+ ],
+ []),
+ ('blanket_agreement.customer', '=',
+ Eval('_parent_sale', {}).get('party', -1)),
+ ]
+
+ @classmethod
+ def _domain_blanket_agreemnt_line_product(cls):
+ return ('product', '=', Eval('product', -1))
+
+ @fields.depends(
+ 'blanket_agreement_line', '_parent_blanket_agreement_line.unit',
+ '_parent_blanket_agreement_line.unit_price', 'unit')
+ def compute_unit_price(self):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ unit_price = super().compute_unit_price()
+ line = self.blanket_agreement_line
+ if (line
+ and self.unit
+ and line.unit
+ and self.unit.category == line.unit.category):
+ unit_price = Uom.compute_price(
+ line.unit, line.unit_price, self.unit)
+ unit_price = round_price(unit_price)
+ return unit_price
+
+ @fields.depends(
+ 'quantity', 'unit',
+ 'blanket_agreement_line',
+ '_parent_blanket_agreement_line.unit',
+ '_parent_blanket_agreement_line.remaining_quantity',
+ methods=['compute_unit_price', 'on_change_quantity'])
+ def on_change_blanket_agreement_line(self):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if self.blanket_agreement_line:
+ line = self.blanket_agreement_line
+ self.unit_price = self.compute_unit_price()
+ if (self.unit and line.unit
+ and self.unit.category == line.unit.category):
+ if line.remaining_quantity is not None:
+ remaining_quantity = Uom.compute_qty(
+ line.unit, line.remaining_quantity, self.unit)
+ if (self.quantity is None
+ or remaining_quantity < self.quantity):
+ self.quantity = remaining_quantity
+ self.on_change_quantity()
+
+ @fields.depends(
+ 'blanket_agreement_line', 'product',
+ '_parent_blanket_agreement_line.product')
+ def on_change_product(self):
+ super().on_change_product()
+ if not self.is_valid_product_for_blanket_agreement():
+ self.blanket_agreement_line = None
+
+ def is_valid_product_for_blanket_agreement(self):
+ if self.blanket_agreement_line:
+ return self.product == self.blanket_agreement_line.product
+
+ def quantity_for_blanket_agreement(self, line, round=True):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if self.unit.category == line.unit.category:
+ return Uom.compute_qty(
+ self.unit, (self.actual_quantity or self.quantity), line.unit,
+ round=round)
+ return 0
+
+
+class BlanketAgreementCreateSale(Wizard):
+ "Create Sale"
+ __name__ = 'sale.blanket_agreement.create_sale'
+ start = StateView(
+ 'sale.blanket_agreement.create_sale.start',
+ 'sale_blanket_agreement'
+ '.sale_blanket_agreement_create_sale_start_form_view', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("Create", 'create_sale', 'tryton-ok', default=True),
+ ])
+ create_sale = StateAction('sale.act_sale_form')
+
+ def default_start(self, fields):
+ line_ids = [
+ line.id for line in self.record.lines
+ if line.remaining_quantity > 0]
+ return {
+ 'blanket_agreement': self.record.id,
+ 'lines': line_ids,
+ }
+
+ def do_create_sale(self, action):
+ if self.start.lines:
+ sale = self.record.get_sale(self.start.lines)
+ sale.save()
+ action['domains'] = []
+ action['views'].reverse()
+ return action, {'res_id': [sale.id]}
+
+
+class BlanketAgreementCreateSaleStart(ModelView):
+ "Create Sale"
+ __name__ = 'sale.blanket_agreement.create_sale.start'
+
+ blanket_agreement = fields.Many2One('sale.blanket_agreement', "Agreement")
+ lines = fields.Many2Many(
+ 'sale.blanket_agreement.line', None, None, "Lines",
+ domain=[('blanket_agreement', '=', Eval('blanket_agreement', -1))])
diff --git a/modules/sale_blanket_agreement/sale.xml b/modules/sale_blanket_agreement/sale.xml
new file mode 100644
index 0000000000..269f70852a
--- /dev/null
+++ b/modules/sale_blanket_agreement/sale.xml
@@ -0,0 +1,231 @@
+
+
+
+
+
+ Sale Blanket Agreement
+
+
+
+
+
+
+
+
+ sale.configuration
+
+ sale_configuration_form
+
+
+
+ Sale Blanket Agreement
+
+
+
+
+
+
+
+
+
+
+
+ Sale Blanket Agreement
+
+
+
+
+ sale.blanket_agreement
+ form
+ sale_blanket_agreement_form
+
+
+
+ sale.blanket_agreement
+ tree
+ sale_blanket_agreement_list
+
+
+
+ Blanket Agreements
+ sale.blanket_agreement
+
+
+
+
+
+
+
+
+
+
+
+
+ Draft
+
+
+
+
+
+
+ Running
+
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+ cancel
+ Cancel
+
+
+
+
+ draft
+ Draft
+
+
+
+
+ run
+ Run
+
+
+
+
+ create_sale
+ Create a sale
+
+
+
+
+ close
+ Close
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sales Blanket Agreement
+
+
+
+
+
+
+
+
+
+ sale.blanket_agreement.line
+ form
+ sale_blanket_agreement_line_form
+
+
+
+ sale.blanket_agreement.line
+ tree
+ sale_blanket_agreement_line_list
+
+
+
+ Sales
+ sale.sale
+
+
+
+
+ form_relate
+ sale.blanket_agreement,-1
+
+
+
+
+ Create a Sale
+ sale.blanket_agreement.create_sale
+ sale.blanket_agreement
+
+
+
+
+
+
+
+ sale.blanket_agreement.create_sale.start
+ form
+ sale_blanket_agreement_create_sale_start_form
+
+
+
+ sale.line
+
+ sale_line_form
+
+
+
+ sale.line
+
+ sale_line_list
+
+
+
+ sale.line
+
+ sale_line_list
+
+
+
+ Sale Lines
+ sale.line
+
+
+
+
+ form_relate
+ sale.blanket_agreement.line,-1
+
+
+
+
diff --git a/modules/sale_blanket_agreement/setup.py b/modules/sale_blanket_agreement/setup.py
new file mode 100755
index 0000000000..33dd1802db
--- /dev/null
+++ b/modules/sale_blanket_agreement/setup.py
@@ -0,0 +1,159 @@
+#!/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 find_packages, setup
+
+
+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_blanket_agreement'
+
+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 blanket agreement',
+ 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-blanket-agreement',
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_blanket_agreement',
+ },
+ keywords='tryton, blanket agreement, sale',
+ package_dir={'trytond.modules.sale_blanket_agreement': '.'},
+ packages=(
+ ['trytond.modules.sale_blanket_agreement']
+ + ['trytond.modules.sale_blanket_agreement.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_blanket_agreement': (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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_blanket_agreement = trytond.modules.sale_blanket_agreement
+ """, # noqa: E501
+ )
diff --git a/modules/sale_blanket_agreement/tests/__init__.py b/modules/sale_blanket_agreement/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_blanket_agreement/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_blanket_agreement/tests/scenario_sale_blanket_agreement.rst b/modules/sale_blanket_agreement/tests/scenario_sale_blanket_agreement.rst
new file mode 100644
index 0000000000..954349d3f8
--- /dev/null
+++ b/modules/sale_blanket_agreement/tests/scenario_sale_blanket_agreement.rst
@@ -0,0 +1,189 @@
+===============================
+Sale Blanket Agreement 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)
+
+ >>> today = datetime.date.today()
+ >>> later = today + relativedelta(days=30)
+
+
+Activate modules::
+
+ >>> config = activate_modules('sale_blanket_agreement')
+
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> SaleBlanketAgreement = Model.get('sale.blanket_agreement')
+ >>> Sale = Model.get('sale.sale')
+
+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_expense = accounts['expense']
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create products::
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+ >>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product1'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('10.000')
+ >>> template.salable = True
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product1, = template.products
+ >>> product1.cost_price = Decimal('8.000')
+ >>> product1.save()
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'Product2'
+ >>> template.default_uom = kg
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('10.000')
+ >>> template.salable = True
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product2, = template.products
+ >>> product2.cost_price = Decimal('8.000')
+ >>> product2.save()
+
+Create sale blanket agreement::
+
+ >>> blanket_agreement = SaleBlanketAgreement()
+ >>> blanket_agreement.customer = customer
+ >>> blanket_agreement.from_date = today
+ >>> blanket_agreement.to_date = later
+ >>> blanket_agreement_line = blanket_agreement.lines.new()
+ >>> blanket_agreement_line.product = product1
+ >>> blanket_agreement_line.quantity = 20.0
+ >>> blanket_agreement_line.unit = unit
+ >>> blanket_agreement_line.unit_price = Decimal('9.0000')
+ >>> blanket_agreement.click('run')
+ >>> blanket_agreement.state
+ 'running'
+
+Create sale from blanket agreement::
+
+ >>> create_sale = Wizard(
+ ... 'sale.blanket_agreement.create_sale',
+ ... [blanket_agreement])
+ >>> len(create_sale.form.lines)
+ 1
+ >>> create_sale.form.lines[0].remaining_quantity
+ 20.0
+ >>> create_sale.execute('create_sale')
+ >>> sale, = create_sale.actions[0]
+
+ >>> line, = sale.lines
+ >>> line.product == product1
+ True
+ >>> line.quantity
+ 20.0
+ >>> line.unit_price
+ Decimal('9.0000')
+ >>> line.quantity = 5.0
+ >>> line.save()
+
+ >>> blanket_agreement.reload()
+ >>> blanket_agreement_line, = blanket_agreement.lines
+ >>> blanket_agreement_line.remaining_quantity
+ 20.0
+
+Confirm sale::
+
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+ >>> blanket_agreement_line.reload()
+ >>> blanket_agreement_line.remaining_quantity
+ 15.0
+
+Try to change product with incompatible unit::
+
+ >>> blanket_agreement.click('draft')
+ >>> line, = blanket_agreement.lines
+ >>> line.product = product2
+ >>> blanket_agreement.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ UOMValidationError: ...
+
+ >>> blanket_agreement.reload()
+ >>> blanket_agreement.click('run')
+
+Try to close blanket agreement with remaining quantity::
+
+ >>> blanket_agreement.click('close') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ BlanketAgreementClosingWarning: ...
+
+Try to sale more than remaining::
+
+
+ >>> sale = Sale(party=customer)
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product1
+ >>> sale_line.unit_price
+ Decimal('10.0000')
+ >>> sale_line.blanket_agreement_line = blanket_agreement_line
+ >>> sale_line.quantity
+ 15.0
+ >>> sale_line.unit_price
+ Decimal('9.0000')
+ >>> sale_line.quantity = 20
+ >>> sale.click('quote') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ BlanketAgreementQuantityWarning: ...
+
+Sale remaining quantity::
+
+ >>> sale_line, = sale.lines
+ >>> sale_line.quantity = 15
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Close blanket agreement::
+
+ >>> blanket_agreement.click('close')
+ >>> blanket_agreement.state
+ 'closed'
diff --git a/modules/sale_blanket_agreement/tests/test_module.py b/modules/sale_blanket_agreement/tests/test_module.py
new file mode 100644
index 0000000000..6fe5f1b97f
--- /dev/null
+++ b/modules/sale_blanket_agreement/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleBlanketAgreementTestCase(ModuleTestCase):
+ "Test Sale Blanket Agreement module"
+ module = 'sale_blanket_agreement'
+
+
+del ModuleTestCase
diff --git a/modules/sale_blanket_agreement/tests/test_scenario.py b/modules/sale_blanket_agreement/tests/test_scenario.py
new file mode 100644
index 0000000000..c80e682a7f
--- /dev/null
+++ b/modules/sale_blanket_agreement/tests/test_scenario.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.
+
+import doctest
+import glob
+import os
+
+from trytond.tests.test_tryton import doctest_checker, doctest_teardown
+
+
+def load_tests(loader, tests, pattern):
+ cwd = os.getcwd()
+ try:
+ os.chdir(os.path.dirname(__file__))
+ for scenario in glob.glob('*.rst'):
+ tests.addTests(doctest.DocFileSuite(
+ scenario, tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ finally:
+ os.chdir(cwd)
+ return tests
diff --git a/modules/sale_blanket_agreement/tox.ini b/modules/sale_blanket_agreement/tox.ini
new file mode 100644
index 0000000000..8ed773ff0d
--- /dev/null
+++ b/modules/sale_blanket_agreement/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_blanket_agreement/* -m unittest discover -s tests
+ coverage report --include=./**/sale_blanket_agreement/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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_blanket_agreement/tryton.cfg b/modules/sale_blanket_agreement/tryton.cfg
new file mode 100644
index 0000000000..d0386dcfd9
--- /dev/null
+++ b/modules/sale_blanket_agreement/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ company
+ product
+ party
+ currency
+ sale
+xml:
+ message.xml
+ product.xml
+ sale.xml
diff --git a/modules/sale_blanket_agreement/view/product_list_agreement_line.xml b/modules/sale_blanket_agreement/view/product_list_agreement_line.xml
new file mode 100644
index 0000000000..92097c2e5d
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/product_list_agreement_line.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_blanket_agreement_create_sale_start_form.xml b/modules/sale_blanket_agreement/view/sale_blanket_agreement_create_sale_start_form.xml
new file mode 100644
index 0000000000..dd48db8874
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_blanket_agreement_create_sale_start_form.xml
@@ -0,0 +1,6 @@
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_blanket_agreement_form.xml b/modules/sale_blanket_agreement/view/sale_blanket_agreement_form.xml
new file mode 100644
index 0000000000..ce87e3698d
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_blanket_agreement_form.xml
@@ -0,0 +1,50 @@
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_blanket_agreement_line_form.xml b/modules/sale_blanket_agreement/view/sale_blanket_agreement_line_form.xml
new file mode 100644
index 0000000000..38bfe1e388
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_blanket_agreement_line_form.xml
@@ -0,0 +1,34 @@
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_blanket_agreement_line_list.xml b/modules/sale_blanket_agreement/view/sale_blanket_agreement_line_list.xml
new file mode 100644
index 0000000000..3e23427bc9
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_blanket_agreement_line_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_blanket_agreement_list.xml b/modules/sale_blanket_agreement/view/sale_blanket_agreement_list.xml
new file mode 100644
index 0000000000..448d4214e3
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_blanket_agreement_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_configuration_form.xml b/modules/sale_blanket_agreement/view/sale_configuration_form.xml
new file mode 100644
index 0000000000..114f401a9c
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_configuration_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_line_form.xml b/modules/sale_blanket_agreement/view/sale_line_form.xml
new file mode 100644
index 0000000000..de21d6f142
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_line_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_blanket_agreement/view/sale_line_list.xml b/modules/sale_blanket_agreement/view/sale_line_list.xml
new file mode 100644
index 0000000000..7596005b2c
--- /dev/null
+++ b/modules/sale_blanket_agreement/view/sale_line_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_complaint/.drone.yml b/modules/sale_complaint/.drone.yml
new file mode 100644
index 0000000000..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_complaint/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_complaint/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_complaint/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_complaint/CHANGELOG b/modules/sale_complaint/CHANGELOG
new file mode 100644
index 0000000000..64f97c0ffd
--- /dev/null
+++ b/modules/sale_complaint/CHANGELOG
@@ -0,0 +1,60 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Add employee on complaint for some states
+* Remove address on complaint
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-01
+* 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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_complaint/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
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..392364bbc2
--- /dev/null
+++ b/modules/sale_complaint/__init__.py
@@ -0,0 +1,20 @@
+# 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, complaint, sale
+
+
+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..1220f9cf3f
--- /dev/null
+++ b/modules/sale_complaint/complaint.py
@@ -0,0 +1,792 @@
+# 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 sql.functions import CharLength
+
+from trytond.i18n import gettext
+from trytond.model import (
+ DeactivableMixin, Index, ModelSQL, ModelView, Workflow, fields)
+from trytond.model.exceptions import AccessError
+from trytond.modules.company.model import (
+ employee_field, reset_employee, set_employee)
+from trytond.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits
+from trytond.pool import Pool
+from trytond.pyson import Bool, Eval, If
+from trytond.transaction import Transaction
+
+
+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',
+ }
+
+ number = fields.Char("Number", readonly=True)
+ reference = fields.Char("Reference")
+ date = fields.Date('Date', states=_states)
+ customer = fields.Many2One(
+ 'party.party', "Customer", required=True, states=_states,
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'company'})
+ company = fields.Many2One(
+ 'company.company', 'Company', required=True,
+ states={
+ 'readonly': _states['readonly'] | Eval('origin'),
+ })
+ type = fields.Many2One('sale.complaint.type', 'Type', required=True,
+ states=_states)
+ origin = fields.Reference('Origin', selection='get_origin',
+ domain={
+ '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']),
+ ],
+ },
+ states={
+ 'readonly': ((Eval('state') != 'draft')
+ | Bool(Eval('actions', [0]))),
+ 'required': Bool(Eval('origin_model')),
+ },
+ depends={'origin_model'})
+ 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)
+ 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={'origin_model'})
+ submitted_by = employee_field(
+ "Submitted By",
+ states=['waiting', 'approved', 'rejected', 'done', 'cancelled'])
+ approved_by = employee_field(
+ "Approved By",
+ states=['approved', 'rejected', 'done', 'cancelled'])
+ rejected_by = employee_field(
+ "Rejected By",
+ states=['approved', 'rejected', 'done', 'cancelled'])
+ cancelled_by = employee_field(
+ "Cancelled By",
+ states=['cancelled'])
+ state = fields.Selection([
+ ('draft', 'Draft'),
+ ('waiting', 'Waiting'),
+ ('approved', 'Approved'),
+ ('rejected', 'Rejected'),
+ ('done', 'Done'),
+ ('cancelled', 'Cancelled'),
+ ], "State", readonly=True, required=True, sort=False)
+
+ @classmethod
+ def __setup__(cls):
+ cls.number.search_unaccented = False
+ cls.reference.search_unaccented = False
+ super(Complaint, cls).__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.update({
+ Index(t, (t.reference, Index.Similarity())),
+ Index(
+ t,
+ (t.state, Index.Equality()),
+ where=t.state.in_(['draft', 'waiting', 'approved'])),
+ })
+ 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'],
+ },
+ })
+
+ 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')
+
+ # Migration from 6.4: rename employee into submitted_by
+ if (table_h.column_exist('employee')
+ and not table_h.column_exist('submitted_by')):
+ table_h.column_rename('employee', 'submitted_by')
+
+ super(Complaint, cls).__register__(module_name)
+
+ @classmethod
+ def _actions_domains(cls):
+ return {
+ None: [],
+ 'sale.sale': ['sale_return'],
+ 'sale.line': ['sale_return'],
+ 'account.invoice': ['credit_note'],
+ 'account.invoice.line': ['credit_note'],
+ }
+
+ @classmethod
+ def order_number(cls, tables):
+ table, _ = tables[None]
+ return [CharLength(table.number), table.number]
+
+ @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)
+ default.setdefault('submitted_by')
+ default.setdefault('approved_by')
+ default.setdefault('rejected_by')
+ default.setdefault('cancelled_by')
+ 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')
+ @set_employee('cancelled_by')
+ def cancel(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ @reset_employee(
+ 'submitted_by', 'approved_by', 'rejected_by', 'cancelled_by')
+ def draft(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('waiting')
+ @set_employee('submitted_by')
+ def wait(cls, complaints):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('approved')
+ @set_employee('approved_by')
+ def approve(cls, complaints):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ transaction = Transaction()
+ context = transaction.context
+ config = Configuration(1)
+ with transaction.set_context(
+ queue_scheduled_at=config.sale_process_after,
+ queue_batch=context.get('queue_batch', True)):
+ cls.__queue__.process(complaints)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('rejected')
+ @set_employee('rejected_by')
+ 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'))),
+ }
+ _line_states = {
+ 'invisible': ~Eval('_parent_complaint', {}
+ ).get('origin_model', 'sale.line').in_(
+ ['sale.line', 'account.invoice.line']),
+ 'readonly': _states['readonly'],
+ }
+
+ complaint = fields.Many2One(
+ 'sale.complaint', 'Complaint', required=True, ondelete='CASCADE',
+ states=_states)
+ 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'],
+ },
+ 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'],
+ },
+ help='Leave empty for all lines.')
+
+ quantity = fields.Float(
+ "Quantity", digits='unit',
+ states=_line_states,
+ help='Leave empty for the same quantity.')
+ unit = fields.Function(fields.Many2One('product.uom', 'Unit',
+ states=_line_states),
+ 'on_change_with_unit')
+ unit_price = Monetary(
+ "Unit Price", currency='currency', digits=price_digits,
+ states=_line_states,
+ help='Leave empty for the same price.')
+
+ amount = fields.Function(Monetary(
+ "Amount", 'currency', digits='currency'),
+ 'on_change_with_amount')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ 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(
+ '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
+
+ @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': [],
+ 'taxes': [],
+ })
+ # 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:
+ __slots__ = ()
+ _states = {
+ 'readonly': (
+ (Eval('complaint_state') != 'draft')
+ | Bool(Eval('_parent_action.result', True))),
+ }
+
+ action = fields.Many2One(
+ 'sale.complaint.action', "Action", ondelete='CASCADE', required=True)
+ quantity = fields.Float(
+ "Quantity", digits='unit', states=_states)
+ unit = fields.Function(
+ fields.Many2One('product.uom', "Unit"), 'on_change_with_unit')
+ unit_price = Monetary(
+ "Unit Price", currency='currency', digits=price_digits,
+ states=_states,
+ help='Leave empty for the same price.')
+
+ amount = fields.Function(Monetary(
+ "Amount", currency='currency', digits='currency'),
+ 'on_change_with_amount')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ 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
+
+ @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
+
+ @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)),
+ ])
+
+ @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('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)),
+ ])
+
+ @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('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..64613bcd5e
--- /dev/null
+++ b/modules/sale_complaint/locale/bg.po
@@ -0,0 +1,437 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Действия"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Щат"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..f4cff04d03
--- /dev/null
+++ b/modules/sale_complaint/locale/ca.po
@@ -0,0 +1,385 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Accions"
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Aprovada per"
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel·lada per"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Rebutjada per"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr "Enviada per"
+
+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,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_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,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_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,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_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 "Rebutjada"
+
+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 "Other Info"
+msgstr "Informació addicional"
+
+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..9bac23af16
--- /dev/null
+++ b/modules/sale_complaint/locale/cs.po
@@ -0,0 +1,405 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..02de45351a
--- /dev/null
+++ b/modules/sale_complaint/locale/de.po
@@ -0,0 +1,387 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Aktionen"
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Genehmigt von"
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Annulliert von"
+
+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,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 "Referenz"
+
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Abgelehnt von"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr "Übermittelt von"
+
+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,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_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,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_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,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_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 "Other Info"
+msgstr "Sonstiges"
+
+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..41543ed35e
--- /dev/null
+++ b/modules/sale_complaint/locale/es.po
@@ -0,0 +1,384 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Acciones"
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Aprobada por"
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancelada por"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Rechazada por"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr "Enviada por"
+
+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,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_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,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_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,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_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 "Other Info"
+msgstr "Información adicional"
+
+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..ca3a560ce2
--- /dev/null
+++ b/modules/sale_complaint/locale/es_419.po
@@ -0,0 +1,385 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr ""
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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 ""
+
+#, 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,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 ""
+
+#, 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 "Other Info"
+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..7405a38d6c
--- /dev/null
+++ b/modules/sale_complaint/locale/et.po
@@ -0,0 +1,406 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Toimingud"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Kinnitatud"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Tühistatud"
+
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Tagasi lükatud"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Olek"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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 ""
+
+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_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 ""
+
+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_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 ""
+
+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_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 "Other Info"
+msgstr ""
+
+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..7e710bfcc6
--- /dev/null
+++ b/modules/sale_complaint/locale/fa.po
@@ -0,0 +1,406 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "اقدامات"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "تصویب شده"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "رد شده"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "وضعیت"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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 ""
+
+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_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 ""
+
+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_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 ""
+
+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_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 "Other Info"
+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..c6c012c5db
--- /dev/null
+++ b/modules/sale_complaint/locale/fi.po
@@ -0,0 +1,404 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..31c2f5fd60
--- /dev/null
+++ b/modules/sale_complaint/locale/fr.po
@@ -0,0 +1,387 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Actions"
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approuvée par"
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Annulée par"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Rejetée par"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr "Soumise par"
+
+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,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_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,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_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,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_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 "Laissez vide pour toutes les lignes."
+
+msgctxt "help:sale.complaint.action,quantity:"
+msgid "Leave empty for the same quantity."
+msgstr "Laissez vide pour la même quantité."
+
+msgctxt "help:sale.complaint.action,sale_lines:"
+msgid "Leave empty for all lines."
+msgstr "Laissez vide pour toutes les lignes."
+
+msgctxt "help:sale.complaint.action,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laissez vide pour le même prix."
+
+msgctxt "help:sale.complaint.action-account.invoice.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laissez vide pour le même prix."
+
+msgctxt "help:sale.complaint.action-sale.line,unit_price:"
+msgid "Leave empty for the same price."
+msgstr "Laissez 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 "Other Info"
+msgstr "Autre information"
+
+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..c669738587
--- /dev/null
+++ b/modules/sale_complaint/locale/hu.po
@@ -0,0 +1,417 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Műveletek"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Megszakítva"
+
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Elutasított"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Státusz"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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 ""
+
+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_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 ""
+
+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_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 ""
+
+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_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 "Other Info"
+msgstr ""
+
+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..f96a5bd833
--- /dev/null
+++ b/modules/sale_complaint/locale/id.po
@@ -0,0 +1,389 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Tindakan"
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Batal"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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"
+
+msgctxt "field:sale.complaint.action,complaint_state:"
+msgid "Complaint State"
+msgstr "Status Keluhan"
+
+msgctxt "field:sale.complaint.action,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+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 "Hasil"
+
+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_price:"
+msgid "Unit Price"
+msgstr "Harga Satuan"
+
+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 "Mata Uang"
+
+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_price:"
+msgid "Unit Price"
+msgstr "Harga Satuan"
+
+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,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_price:"
+msgid "Unit Price"
+msgstr "Harga Satuan"
+
+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 "Other Info"
+msgstr ""
+
+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..de168f0b4f
--- /dev/null
+++ b/modules/sale_complaint/locale/it.po
@@ -0,0 +1,416 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Azioni"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Annullato"
+
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Rifiutato"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Stato"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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 "Valuta"
+
+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_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 "Valuta"
+
+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_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 "Valuta"
+
+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_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 "Other Info"
+msgstr ""
+
+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..3b7a52c448
--- /dev/null
+++ b/modules/sale_complaint/locale/lo.po
@@ -0,0 +1,433 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "ການປະຕິບັດ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "ອະນຸມັດແລ້ວ"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel"
+
+#, 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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "ສະຖານະ"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..0fe5914079
--- /dev/null
+++ b/modules/sale_complaint/locale/lt.po
@@ -0,0 +1,405 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..c3748f2a1f
--- /dev/null
+++ b/modules/sale_complaint/locale/nl.po
@@ -0,0 +1,386 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Acties"
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Goedgekeurd door"
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Geannuleerd door"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Afgewezen door"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr "Ingediend door"
+
+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,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_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,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_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,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_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"
+
+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 "Other Info"
+msgstr "Overige informatie"
+
+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..5d3df98d7e
--- /dev/null
+++ b/modules/sale_complaint/locale/pl.po
@@ -0,0 +1,419 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Akcje"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Anulowano"
+
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Odrzucono"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Stan"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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 ""
+
+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_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 ""
+
+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_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 ""
+
+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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..42bb597d9a
--- /dev/null
+++ b/modules/sale_complaint/locale/pt.po
@@ -0,0 +1,417 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Ações"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancelado"
+
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Rejeitado"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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 ""
+
+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_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 ""
+
+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_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 ""
+
+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_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 "Other Info"
+msgstr ""
+
+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..7fb7e2cd29
--- /dev/null
+++ b/modules/sale_complaint/locale/ro.po
@@ -0,0 +1,383 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr ""
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr ""
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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 "Other Info"
+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..c98c9dc7f2
--- /dev/null
+++ b/modules/sale_complaint/locale/ru.po
@@ -0,0 +1,438 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Действия"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Штат"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..97591a5ceb
--- /dev/null
+++ b/modules/sale_complaint/locale/sl.po
@@ -0,0 +1,417 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "Ukrepi"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Preklicano"
+
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.complaint,rejected_by:"
+msgid "Rejected By"
+msgstr "Zavrnjeno"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "Stanje"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+msgstr ""
+
+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 ""
+
+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_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 ""
+
+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_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 ""
+
+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_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 "Other Info"
+msgstr ""
+
+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..c6c012c5db
--- /dev/null
+++ b/modules/sale_complaint/locale/tr.po
@@ -0,0 +1,404 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr "Process"
diff --git a/modules/sale_complaint/locale/uk.po b/modules/sale_complaint/locale/uk.po
new file mode 100644
index 0000000000..1c11432d8f
--- /dev/null
+++ b/modules/sale_complaint/locale/uk.po
@@ -0,0 +1,383 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr ""
+
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr ""
+
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr ""
+
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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 ""
+
+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,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_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 ""
+
+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,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_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 ""
+
+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 "Other Info"
+msgstr ""
+
+msgctxt "view:sale.complaint:"
+msgid "Process"
+msgstr ""
diff --git a/modules/sale_complaint/locale/zh_CN.po b/modules/sale_complaint/locale/zh_CN.po
new file mode 100644
index 0000000000..1407c72b91
--- /dev/null
+++ b/modules/sale_complaint/locale/zh_CN.po
@@ -0,0 +1,416 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+#, fuzzy
+msgctxt "field:sale.complaint,actions:"
+msgid "Actions"
+msgstr "操作"
+
+#, fuzzy
+msgctxt "field:sale.complaint,approved_by:"
+msgid "Approved By"
+msgstr "Approved"
+
+#, fuzzy
+msgctxt "field:sale.complaint,cancelled_by:"
+msgid "Cancelled By"
+msgstr "Cancel"
+
+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,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,rejected_by:"
+msgid "Rejected By"
+msgstr "Reject"
+
+#, fuzzy
+msgctxt "field:sale.complaint,state:"
+msgid "State"
+msgstr "状态"
+
+msgctxt "field:sale.complaint,submitted_by:"
+msgid "Submitted By"
+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,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_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,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_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,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_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"
+
+msgctxt "view:sale.complaint:"
+msgid "Other Info"
+msgstr ""
+
+#, 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..7ab362f70a
--- /dev/null
+++ b/modules/sale_complaint/sale.py
@@ -0,0 +1,79 @@
+# 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.pool import Pool, PoolMeta
+from trytond.pyson import Eval, Id
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ complaint_sequence = fields.MultiValue(fields.Many2One(
+ 'ir.sequence', "Complaint Sequence", required=True,
+ 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", required=True,
+ domain=[
+ ('sequence_type', '=',
+ Id('sale_complaint', 'sequence_type_complaint')),
+ ('company', 'in', [Eval('company', -1), None]),
+ ])
+
+ @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..401725cb57
--- /dev/null
+++ b/modules/sale_complaint/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 find_packages, setup
+
+
+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 = ['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 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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_complaint = trytond.modules.sale_complaint
+ """,
+ )
diff --git a/modules/sale_complaint/tests/__init__.py b/modules/sale_complaint/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_complaint/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_complaint/tests/test_module.py
new file mode 100644
index 0000000000..065167079e
--- /dev/null
+++ b/modules/sale_complaint/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SaleComplaintTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Complaint module'
+ module = 'sale_complaint'
+
+
+del ModuleTestCase
diff --git a/modules/sale_complaint/tests/test_scenario.py b/modules/sale_complaint/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_complaint/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_complaint/tox.ini b/modules/sale_complaint/tox.ini
new file mode 100644
index 0000000000..94c03cbf52
--- /dev/null
+++ b/modules/sale_complaint/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_complaint/* -m unittest discover -s tests
+ coverage report --include=./**/sale_complaint/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..258b0438e8
--- /dev/null
+++ b/modules/sale_complaint/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.7.0
+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..774f2c479a
--- /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..e3179c3cd4
--- /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..e3eba3775d
--- /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..32628f7a87
--- /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..e44a4dbe75
--- /dev/null
+++ b/modules/sale_complaint/view/complaint_form.xml
@@ -0,0 +1,51 @@
+
+
+
diff --git a/modules/sale_complaint/view/complaint_list.xml b/modules/sale_complaint/view/complaint_list.xml
new file mode 100644
index 0000000000..430a70f1cc
--- /dev/null
+++ b/modules/sale_complaint/view/complaint_list.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_credit_limit/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_credit_limit/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_credit_limit/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_credit_limit/CHANGELOG b/modules/sale_credit_limit/CHANGELOG
new file mode 100644
index 0000000000..712c3b1530
--- /dev/null
+++ b/modules/sale_credit_limit/CHANGELOG
@@ -0,0 +1,60 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..51a574630e
--- /dev/null
+++ b/modules/sale_credit_limit/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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_credit_limit/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..78da1b6ee0
--- /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, 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..d209f7268f
--- /dev/null
+++ b/modules/sale_credit_limit/sale.py
@@ -0,0 +1,27 @@
+# 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'
+
+ def must_check_credit_limit(self):
+ return self.shipment_method == 'order'
+
+ @property
+ def credit_limit_amount(self):
+ "Amount to check against credit limit"
+ return self.untaxed_amount
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('confirmed')
+ def confirm(cls, sales):
+ for sale in sales:
+ if sale.must_check_credit_limit():
+ party = sale.invoice_party or sale.party
+ party.check_credit_limit(
+ sale.credit_limit_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..411b89335d
--- /dev/null
+++ b/modules/sale_credit_limit/setup.py
@@ -0,0 +1,146 @@
+#!/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_credit_limit = trytond.modules.sale_credit_limit
+ """,
+ )
diff --git a/modules/sale_credit_limit/tests/__init__.py b/modules/sale_credit_limit/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_credit_limit/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_credit_limit/tests/test_module.py b/modules/sale_credit_limit/tests/test_module.py
new file mode 100644
index 0000000000..31fde1e612
--- /dev/null
+++ b/modules/sale_credit_limit/tests/test_module.py
@@ -0,0 +1,126 @@
+# 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.exceptions import UserWarning
+from trytond.modules.account.tests import create_chart, get_fiscalyear
+from trytond.modules.account_invoice.tests import set_invoice_sequences
+from trytond.modules.company.tests import (
+ CompanyTestMixin, create_company, set_company)
+from trytond.pool import Pool
+from trytond.tests.test_tryton import ModuleTestCase, with_transaction
+
+
+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'))
+
+
+del ModuleTestCase
diff --git a/modules/sale_credit_limit/tox.ini b/modules/sale_credit_limit/tox.ini
new file mode 100644
index 0000000000..6171b1505b
--- /dev/null
+++ b/modules/sale_credit_limit/tox.ini
@@ -0,0 +1,16 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+commands =
+ coverage run --include=./**/sale_credit_limit/* -m unittest discover -s tests
+ coverage report --include=./**/sale_credit_limit/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..5a722b51b5
--- /dev/null
+++ b/modules/sale_credit_limit/tryton.cfg
@@ -0,0 +1,9 @@
+[tryton]
+version=6.7.0
+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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_discount/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_discount/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_discount/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_discount/CHANGELOG b/modules/sale_discount/CHANGELOG
new file mode 100644
index 0000000000..2b3a1d388b
--- /dev/null
+++ b/modules/sale_discount/CHANGELOG
@@ -0,0 +1,17 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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
+* 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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_discount/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..66164a9c06
--- /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..7712a4b98a
--- /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 "Prezzo Base"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Sconto"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Totale sconto"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Tasso di sconto"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Sconto"
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..fc9aeecc35
--- /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 "Preț Baza"
+
+msgctxt "field:sale.line,discount:"
+msgid "Discount"
+msgstr "Reducere"
+
+msgctxt "field:sale.line,discount_amount:"
+msgid "Discount Amount"
+msgstr "Sumă Reducere"
+
+msgctxt "field:sale.line,discount_rate:"
+msgid "Discount Rate"
+msgstr "Rata Reducere"
+
+msgctxt "view:sale.line:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.line:"
+msgid "Discount"
+msgstr "Reducere"
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/uk.po b/modules/sale_discount/locale/uk.po
new file mode 100644
index 0000000000..c18f45b463
--- /dev/null
+++ b/modules/sale_discount/locale/uk.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..8669fde34f
--- /dev/null
+++ b/modules/sale_discount/sale.py
@@ -0,0 +1,147 @@
+# 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.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits, round_price
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ base_price = Monetary(
+ "Base Price", currency='currency', digits=price_digits,
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ })
+
+ discount_rate = fields.Function(fields.Numeric(
+ "Discount Rate", digits=(16, 4),
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ }),
+ 'on_change_with_discount_rate', setter='set_discount_rate')
+ discount_amount = fields.Function(Monetary(
+ "Discount Amount", currency='currency', digits=price_digits,
+ states={
+ 'invisible': Eval('type') != 'line',
+ 'readonly': Eval('sale_state') != 'draft',
+ }),
+ '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 and self.product.list_price is not None:
+ 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..8a77bbb7ba
--- /dev/null
+++ b/modules/sale_discount/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_discount = trytond.modules.sale_discount
+ """, # noqa: E501
+ )
diff --git a/modules/sale_discount/tests/__init__.py b/modules/sale_discount/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_discount/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_discount/tests/test_module.py
new file mode 100644
index 0000000000..eb54765baa
--- /dev/null
+++ b/modules/sale_discount/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleDiscountTestCase(ModuleTestCase):
+ 'Test Sale Discount module'
+ module = 'sale_discount'
+
+
+del ModuleTestCase
diff --git a/modules/sale_discount/tests/test_scenario.py b/modules/sale_discount/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_discount/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_discount/tox.ini b/modules/sale_discount/tox.ini
new file mode 100644
index 0000000000..b533ee79cb
--- /dev/null
+++ b/modules/sale_discount/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_discount/* -m unittest discover -s tests
+ coverage report --include=./**/sale_discount/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..9e99b50ecf
--- /dev/null
+++ b/modules/sale_discount/tryton.cfg
@@ -0,0 +1,8 @@
+[tryton]
+version=6.7.0
+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..cf3bff67db
--- /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..4177a23e15
--- /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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_extra/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_extra/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_extra/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_extra/CHANGELOG b/modules/sale_extra/CHANGELOG
new file mode 100644
index 0000000000..70428c2ff4
--- /dev/null
+++ b/modules/sale_extra/CHANGELOG
@@ -0,0 +1,56 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..b97a61c3dd
--- /dev/null
+++ b/modules/sale_extra/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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_extra/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..ba779186aa
--- /dev/null
+++ b/modules/sale_extra/__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.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..98e1f03a61
--- /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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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.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..e7ff5ad104
--- /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:"
+msgid "Currency"
+msgstr "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,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+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.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..0ff4bc6dcb
--- /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:"
+msgid "Currency"
+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 ""
+
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+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 ""
+
+#, 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..d26ecdeab0
--- /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:"
+msgid "Currency"
+msgstr "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,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+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.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..58bff41211
--- /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:"
+msgid "Currency"
+msgstr "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,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+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.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..ea55a83874
--- /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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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.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..7ce352ab5b
--- /dev/null
+++ b/modules/sale_extra/locale/et.po
@@ -0,0 +1,104 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+msgstr "Valuuta numbriväärtus"
+
+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.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..ac46640ed1
--- /dev/null
+++ b/modules/sale_extra/locale/fa.po
@@ -0,0 +1,101 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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.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..76e5ba6b04
--- /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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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 ""
+
+#, 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..3ae211ba52
--- /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:"
+msgid "Currency"
+msgstr "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,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+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.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..11979baa02
--- /dev/null
+++ b/modules/sale_extra/locale/hu.po
@@ -0,0 +1,104 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Társaság"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+msgstr "Tizedes vessző utáni számjegy"
+
+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.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..646d17647e
--- /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:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+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,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+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.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..06bc804060
--- /dev/null
+++ b/modules/sale_extra/locale/it.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+msgstr "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,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+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.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 "Vendite Extra"
+
+msgctxt "model:ir.rule.group,name:rule_group_extra_companies"
+msgid "User in companies"
+msgstr "Utente nelle aziende"
+
+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..c58008152f
--- /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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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.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..1bcc105ed9
--- /dev/null
+++ b/modules/sale_extra/locale/lt.po
@@ -0,0 +1,105 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+msgstr "Valiutos skaitmenų skaičius"
+
+#, 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 ""
+
+#, 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..40e0867e18
--- /dev/null
+++ b/modules/sale_extra/locale/nl.po
@@ -0,0 +1,99 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+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,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+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.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"
+
+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..6abaffd815
--- /dev/null
+++ b/modules/sale_extra/locale/pl.po
@@ -0,0 +1,107 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+msgstr "Cyfry waluty"
+
+#, 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"
+
+#, 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..7c27cd1bdc
--- /dev/null
+++ b/modules/sale_extra/locale/pt.po
@@ -0,0 +1,102 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+msgstr "Dígitos Decimais da Moeda"
+
+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.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..758be43f10
--- /dev/null
+++ b/modules/sale_extra/locale/ro.po
@@ -0,0 +1,101 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Companie"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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 ""
+
+#, fuzzy
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+msgstr "Zecimale valută"
+
+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.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..e5bf50e7c6
--- /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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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.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..5971ce1ce8
--- /dev/null
+++ b/modules/sale_extra/locale/sl.po
@@ -0,0 +1,104 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.extra,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:sale.extra,currency:"
+msgid "Currency"
+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"
+
+#, fuzzy
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+msgstr "Decimalke"
+
+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.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..76e5ba6b04
--- /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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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 ""
+
+#, 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/uk.po b/modules/sale_extra/locale/uk.po
new file mode 100644
index 0000000000..2109bcc6df
--- /dev/null
+++ b/modules/sale_extra/locale/uk.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:"
+msgid "Currency"
+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,currency:"
+msgid "Currency"
+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.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/zh_CN.po b/modules/sale_extra/locale/zh_CN.po
new file mode 100644
index 0000000000..15e1239c8c
--- /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:"
+msgid "Currency"
+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 ""
+
+msgctxt "field:sale.extra.line,currency:"
+msgid "Currency"
+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 ""
+
+#, 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..0b072d717f
--- /dev/null
+++ b/modules/sale_extra/sale.py
@@ -0,0 +1,276 @@
+# 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.model import (
+ DeactivableMixin, MatchMixin, ModelSQL, ModelView, Workflow, fields,
+ sequence_ordered)
+from trytond.modules.currency.fields import Monetary
+from trytond.pool import Pool, PoolMeta
+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,
+ 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),
+ ])
+ 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),
+ ])
+ price_list = fields.Many2One('product.price_list', 'Price List',
+ ondelete='CASCADE',
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ])
+ sale_amount = Monetary(
+ "Sale Amount", currency='currency', digits='currency')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+ 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(self, name=None):
+ if self.company:
+ return self.company.currency.id
+
+ @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 = Monetary(
+ "Sale Amount", currency='currency', digits='currency')
+ 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='unit', required=True)
+ unit = fields.Many2One('product.uom', 'Unit', required=True,
+ domain=[
+ ('category', '=', Eval('product_uom_category', -1)),
+ ])
+ free = fields.Boolean('Free')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ @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('product')
+ def on_change_product(self):
+ if self.product:
+ self.unit = self.product.sale_uom
+
+ @staticmethod
+ def default_free():
+ return False
+
+ @fields.depends('extra', '_parent_extra.currency')
+ def on_change_with_currency(self, name=None):
+ if self.extra and self.extra.currency:
+ return self.extra.currency.id
+
+ 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..7cc33b4b4b
--- /dev/null
+++ b/modules/sale_extra/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_extra = trytond.modules.sale_extra
+ """,
+ )
diff --git a/modules/sale_extra/tests/__init__.py b/modules/sale_extra/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_extra/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_extra/tests/test_module.py
new file mode 100644
index 0000000000..2db2056664
--- /dev/null
+++ b/modules/sale_extra/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SaleExtraTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Extra module'
+ module = 'sale_extra'
+
+
+del ModuleTestCase
diff --git a/modules/sale_extra/tests/test_scenario.py b/modules/sale_extra/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_extra/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_extra/tox.ini b/modules/sale_extra/tox.ini
new file mode 100644
index 0000000000..cd29d61688
--- /dev/null
+++ b/modules/sale_extra/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_extra/* -m unittest discover -s tests
+ coverage report --include=./**/sale_extra/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..58dbe8a079
--- /dev/null
+++ b/modules/sale_extra/tryton.cfg
@@ -0,0 +1,12 @@
+[tryton]
+version=6.7.0
+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..f273d8399a
--- /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..b45ef267ef
--- /dev/null
+++ b/modules/sale_gift_card/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_gift_card/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_gift_card/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_gift_card/CHANGELOG b/modules/sale_gift_card/CHANGELOG
new file mode 100644
index 0000000000..4067946c46
--- /dev/null
+++ b/modules/sale_gift_card/CHANGELOG
@@ -0,0 +1,18 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-01
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Manage gift card on POS
+
+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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_gift_card/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..6a12ebf437
--- /dev/null
+++ b/modules/sale_gift_card/__init__.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.pool import Pool
+
+from . import account, product, sale, 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.GiftCardReport,
+ sale.GiftCardEmail,
+ module='sale_gift_card', type_='report')
+ Pool.register(
+ sale.GiftCard_POS,
+ sale.POSSale,
+ sale.POSSaleLine,
+ sale.POSPayGiftCard,
+ module='sale_gift_card', type_='model', depends=['sale_point'])
+ Pool.register(
+ sale.POSPay,
+ module='sale_gift_card', type_='wizard', depends=['sale_point'])
diff --git a/modules/sale_gift_card/account.py b/modules/sale_gift_card/account.py
new file mode 100644
index 0000000000..5b9c749ca8
--- /dev/null
+++ b/modules/sale_gift_card/account.py
@@ -0,0 +1,98 @@
+# 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.modules.company.model import CompanyValueMixin
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Bool, Eval, If
+
+
+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)),
+ ])
+ gift_card_account_revenue = fields.Many2One(
+ 'account.account', "Gift Card Revenue",
+ domain=[
+ ('type.gift_card', '=', True),
+ ('closed', '!=', True),
+ ('company', '=', Eval('company', -1)),
+ ])
+
+
+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',
+ })
+ 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..9267f8ce06
--- /dev/null
+++ b/modules/sale_gift_card/doc/index.rst
@@ -0,0 +1,12 @@
+#####################
+Sale Gift Card Module
+#####################
+
+The *Sale Gift Card Module* manages the selling and redeeming of gift cards.
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ usage
+ releases
diff --git a/modules/sale_gift_card/doc/releases.rst b/modules/sale_gift_card/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_gift_card/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
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..478ab530e2
--- /dev/null
+++ b/modules/sale_gift_card/email.html
@@ -0,0 +1,22 @@
+
+
+
+ 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/gift_card.fodt b/modules/sale_gift_card/gift_card.fodt
new file mode 100644
index 0000000000..5a019640de
--- /dev/null
+++ b/modules/sale_gift_card/gift_card.fodt
@@ -0,0 +1,287 @@
+
+
+
+ 2021-08-24T17:09:33.815571391LibreOffice/7.1.3.2$Linux_X86_64 LibreOffice_project/10$Build-22021-08-24T17:22:12.187453618PT12M35S7
+
+
+ 0
+ 0
+ 17323
+ 8592
+ true
+ false
+
+
+ view2
+ 1136
+ 1512
+ 0
+ 0
+ 17321
+ 8590
+ 0
+ 0
+ false
+ 280
+ false
+ false
+
+
+
+
+ false
+ false
+ false
+ true
+ true
+ true
+ true
+ true
+ false
+ 0
+ false
+ false
+ false
+ true
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ true
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ false
+ false
+ true
+ false
+ false
+ false
+ true
+ 0
+ 1
+ true
+ false
+
+ high-resolution
+ true
+
+
+ false
+ false
+ true
+ false
+ true
+ true
+ false
+ true
+ mwH+/1JJQ09IX0FmaWNpb18yMDIwRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ1VQUzpSSUNPSF9BZmljaW9fMjAyMEQAAAAAAAAAAAAWAAMAtwAAAAAAAAAEAAhSAAAEdAAASm9iRGF0YSAxCnByaW50ZXI9UklDT0hfQWZpY2lvXzIwMjBECm9yaWVudGF0aW9uPVBvcnRyYWl0CmNvcGllcz0xCmNvbGxhdGU9ZmFsc2UKbWFyZ2luZGFqdXN0bWVudD0wLDAsMCwwCmNvbG9yZGVwdGg9MjQKcHNsZXZlbD0wCnBkZmRldmljZT0xCmNvbG9yZGV2aWNlPTAKUFBEQ29udGV4RGF0YQpQYWdlU2l6ZTpBNAAAEgBDT01QQVRfRFVQTEVYX01PREUUAER1cGxleE1vZGU6OkxvbmdFZGdl
+ true
+ 1111966
+
+ true
+ false
+ true
+ 0
+ RICOH_Aficio_2020D
+ false
+ false
+ false
+ true
+ false
+ true
+ false
+ false
+ false
+ false
+ true
+ false
+
+ false
+ false
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ 1111966
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <for each="card in records">
+ <card.company.rec_name>
+ <card.number>
+ Value: <format_currency(card.value, None, card.currency)>
+ </for>
+
+
+
\ No newline at end of file
diff --git a/modules/sale_gift_card/locale/bg.po b/modules/sale_gift_card/locale/bg.po
new file mode 100644
index 0000000000..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/bg.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..5a07055f6c
--- /dev/null
+++ b/modules/sale_gift_card/locale/ca.po
@@ -0,0 +1,272 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "Correu electrònic de la targeta regal"
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "És una targeta regal"
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Es el servei de targetes regal"
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr "Correu electrònic"
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - Gift Card"
+msgstr "Pagament TPV - 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 %(value)s for %(company)s."
+msgstr "Heu rebut una targeta regal de %(valor)s de l'empresa %(company)s."
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr "Valor:"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Targeta regal"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr "Targetes regal"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr "Afegeix"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+msgstr "Targeta 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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/cs.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..9e1da9d998
--- /dev/null
+++ b/modules/sale_gift_card/locale/de.po
@@ -0,0 +1,275 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "E-Mail Geschenkgutschein"
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Ist Geschenkgutschein"
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Ist Geschenkgutschein Für Dienstleistung"
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr "E-Mail"
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+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 "help:sale.point.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"
+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 Warenbewegung \"%(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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - Gift Card"
+msgstr "Point of Sale Zahlung - 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 %(value)s for %(company)s."
+msgstr ""
+"Sie haben einen Geschenkgutschein in Höhe von %(value)s von %(company)s "
+"erhalten."
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr "Wert:"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr "Geschenkgutscheine"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr "Hinzufügen"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+msgstr "Geschenkgutschein"
diff --git a/modules/sale_gift_card/locale/es.po b/modules/sale_gift_card/locale/es.po
new file mode 100644
index 0000000000..18cc9fafc2
--- /dev/null
+++ b/modules/sale_gift_card/locale/es.po
@@ -0,0 +1,273 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "Correo electrónico de la tarjeta regalo"
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Es tarjeta regalo"
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Es el servicio de tarjetas regalo"
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr "Correo electrónico"
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - Gift Card"
+msgstr "Pago TPV - 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 %(value)s for %(company)s."
+msgstr ""
+"Has recibido una tarjeta regalo de %(value)s de la empresa %(company)s."
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr "Valor:"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Tarjeta regalo"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr "Tarjetas regalo"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr "Añadir"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+msgstr "Tarjeta 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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/es_419.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/et.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/fa.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/fi.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..0beed348ac
--- /dev/null
+++ b/modules/sale_gift_card/locale/fr.po
@@ -0,0 +1,272 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "E-mail de la carte cadeau"
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Est une carte cadeau"
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Est un service de carte cadeau"
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr "E-mail"
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+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 "help:sale.point.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"
+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 société 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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - Gift Card"
+msgstr "Paiement PDV - 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 %(value)s for %(company)s."
+msgstr "Vous avez reçu une carte cadeau de %(value)s for %(company)s."
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr "Valeur :"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr "Cartes cadeaux"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr "Ajouter"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+msgstr "Carte cadeau"
diff --git a/modules/sale_gift_card/locale/hu.po b/modules/sale_gift_card/locale/hu.po
new file mode 100644
index 0000000000..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/hu.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..13a0c315c3
--- /dev/null
+++ b/modules/sale_gift_card/locale/id.po
@@ -0,0 +1,268 @@
+#
+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 "Perusahaan"
+
+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 "Perusahaan"
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr ""
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Asal"
+
+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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..bc1f049aea
--- /dev/null
+++ b/modules/sale_gift_card/locale/it.po
@@ -0,0 +1,268 @@
+#
+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 "Valuta"
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Origine"
+
+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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/lo.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/lt.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..cbdf63ec2f
--- /dev/null
+++ b/modules/sale_gift_card/locale/nl.po
@@ -0,0 +1,272 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:account.account.type,gift_card:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "field:account.account.type.template,gift_card:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "field:account.configuration,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Kosten waardebon"
+
+msgctxt "field:account.configuration,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Inkomsten waardebon"
+
+msgctxt "field:account.configuration.gift_card_account,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_expense:"
+msgid "Gift Card Expense"
+msgstr "Kosten waardebon"
+
+msgctxt ""
+"field:account.configuration.gift_card_account,gift_card_account_revenue:"
+msgid "Gift Card Revenue"
+msgstr "Inkomsten waardebon"
+
+msgctxt "field:product.product,gift_card:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "field:product.template,gift_card:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "field:sale.configuration,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Waardebon reeks"
+
+msgctxt "field:sale.configuration.gift_card.sequence,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.configuration.gift_card.sequence,gift_card_sequence:"
+msgid "Gift Card Sequence"
+msgstr "Waardebon reeks"
+
+msgctxt "field:sale.gift_card,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.gift_card,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.gift_card,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.gift_card,origin:"
+msgid "Origin"
+msgstr "Oorsprong(herkomst)"
+
+msgctxt "field:sale.gift_card,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.gift_card,spent_on:"
+msgid "Spent On"
+msgstr "Uitgegeven aan"
+
+msgctxt "field:sale.gift_card,value:"
+msgid "Value"
+msgstr "Waarde"
+
+msgctxt "field:sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "E-mail waardebon"
+
+msgctxt "field:sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "field:sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Is een waardebon"
+
+msgctxt "field:sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Is een waardebon dienst"
+
+msgctxt "field:sale.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr "E-mail waardebon"
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr "Is een waardebon"
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr "Is cadeaukaartservice"
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr "E-mail"
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "field:stock.move,gift_cards:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "field:stock.move,gift_cards_required:"
+msgid "Gift Cards Required"
+msgstr "Waardebon vereist"
+
+msgctxt "help:sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr "Laat leeg voor het e-mailadres van de klant."
+
+msgctxt "help:sale.point.sale.line,gift_card_email:"
+msgid "Leave empty for the customer email."
+msgstr "Laat leeg voor het e-mailadres van de klant."
+
+msgctxt "model:account.configuration.gift_card_account,name:"
+msgid "Account Configuration Gift Card Account"
+msgstr "Accountconfiguratie Waardebon-account"
+
+msgctxt "model:ir.action,name:act_gift_card_form"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "model:ir.action,name:report_gift_card"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "model:ir.action,name:report_gift_card_email"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+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 "In afwachting"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_gift_card_form_domain_sent"
+msgid "Sent"
+msgstr "Verzonden"
+
+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 ""
+"De standaardmaateenheid voor de waardebon \"%(template)s\" moet \"%(unit)s\""
+" zijn."
+
+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 ""
+"Om de boeking \"%(move)s\" uit te voeren, moet u exact %(quantity)d "
+"waardebon(nen) gebruiken."
+
+msgctxt "model:ir.message,text:msg_gift_card_number_unique"
+msgid "The numbers for each company's gift cards must be unique."
+msgstr "De nummers voor de waardebonnen van elk bedrijf moeten uniek zijn."
+
+msgctxt "model:ir.rule.group,name:rule_group_gift_card_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_gift_card"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "model:ir.ui.menu,name:menu_gift_card_form"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "model:res.group,name:group_gift_card_admin"
+msgid "Gift Card Administration"
+msgstr "Waardebon administratie"
+
+msgctxt "model:sale.configuration.gift_card.sequence,name:"
+msgid "Gift Card Configuration Sequence"
+msgstr "Configuratievolgorde van waardebonnen"
+
+msgctxt "model:sale.gift_card,name:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - Gift Card"
+msgstr "POS Pay - Cadeaukaart"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "Here is your code:"
+msgstr "Hier is je code:"
+
+msgctxt "report:sale.gift_card.email:"
+msgid "You received a gift card of %(value)s for %(company)s."
+msgstr "U hebt een waardebon van %(value)s ontvangen voor %(company)s."
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr "Waarde:"
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr "Waardebon"
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr "Waardebonnen"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr "Toevoegen"
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+msgstr "Waardebom"
diff --git a/modules/sale_gift_card/locale/pl.po b/modules/sale_gift_card/locale/pl.po
new file mode 100644
index 0000000000..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/pl.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/pt.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/ro.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/ru.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/sl.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/tr.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+msgstr ""
diff --git a/modules/sale_gift_card/locale/uk.po b/modules/sale_gift_card/locale/uk.po
new file mode 100644
index 0000000000..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/uk.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..e593d36448
--- /dev/null
+++ b/modules/sale_gift_card/locale/zh_CN.po
@@ -0,0 +1,268 @@
+#
+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,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.point.sale,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_card_email:"
+msgid "Gift Card Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,gift_cards:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card:"
+msgid "Is Gift Card"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,is_gift_card_service:"
+msgid "Is Gift Card Service"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,email:"
+msgid "Email"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.pay.gift_card,sale:"
+msgid "Sale"
+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 "help:sale.point.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"
+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 "model:sale.point.sale.pay.gift_card,name:"
+msgid "POS Pay - 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 %(value)s for %(company)s."
+msgstr ""
+
+msgctxt "report:sale.gift_card:"
+msgid "Value:"
+msgstr ""
+
+msgctxt "view:account.configuration:"
+msgid "Gift Card"
+msgstr ""
+
+msgctxt "view:sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "Gift Cards"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,add_gift_card:"
+msgid "Add"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,gift_card,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,gift_card:"
+msgid "Gift Card"
+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..6074a00134
--- /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 Pool, PoolMeta
+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']),
+ })
+
+ @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_fields(cls, templates, field_names):
+ pool = Pool()
+ ModelData = pool.get('ir.model.data')
+ UoM = pool.get('product.uom')
+ super().validate_fields(templates, field_names)
+ if field_names & {'gift_card', 'default_uom'}:
+ 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..56c2627b8a
--- /dev/null
+++ b/modules/sale_gift_card/sale.py
@@ -0,0 +1,555 @@
+# 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.functions import CharLength
+from sql.operators import Equal
+
+from trytond.config import config
+from trytond.model import Exclude, ModelSQL, ModelView, Workflow, fields
+from trytond.modules.company.model import CompanyValueMixin
+from trytond.modules.currency.fields import Monetary
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Bool, Eval, Id
+from trytond.report import Report, get_email
+from trytond.sendmail import sendmail_transactional
+from trytond.tools.email_ import set_from_header
+from trytond.transaction import Transaction
+from trytond.wizard import Button, StateTransition, StateView
+
+
+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')),
+ ])
+
+
+class GiftCard(ModelSQL, ModelView):
+ "Gift Card"
+ __name__ = 'sale.gift_card'
+ _rec_name = 'number'
+
+ _states = {
+ 'readonly': Bool(Eval('origin')) | Bool(Eval('spent_on')),
+ }
+
+ number = fields.Char(
+ "Number", required=True, states=_states)
+ company = fields.Many2One(
+ 'company.company', "Company", required=True, states=_states)
+ product = fields.Many2One(
+ 'product.product', "Product", required=True,
+ domain=[
+ ('gift_card', '=', True),
+ ],
+ context={
+ 'company': Eval('company', -1),
+ },
+ states=_states, depends={'company'})
+ value = Monetary(
+ "Value", currency='currency', digits='currency', required=True,
+ states=_states)
+ currency = fields.Many2One(
+ 'currency.currency', "Currency", required=True, states=_states)
+
+ origin = fields.Reference("Origin", selection='get_origin', readonly=True)
+ spent_on = fields.Reference(
+ "Spent On", selection='get_spent_on', readonly=True)
+
+ del _states
+
+ @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 order_number(cls, tables):
+ table, _ = tables[None]
+ return [CharLength(table.number), table.number]
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @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')
+ from_cfg = config.get('email', 'from')
+ for gift_card in gift_cards:
+ email = gift_card._email
+ if not email:
+ continue
+ languages = gift_card._languages
+ if not languages:
+ languages.append(Lang.get())
+ msg, title = get_email(
+ 'sale.gift_card.email', gift_card, languages)
+ set_from_header(msg, from_cfg, from_ or from_cfg)
+ msg['To'] = email
+ msg['Subject'] = Header(title, 'utf-8')
+ sendmail_transactional(from_cfg, [email], msg, strict=True)
+
+
+class GiftCardReport(Report):
+ __name__ = 'sale.gift_card'
+
+ @classmethod
+ def _get_records(cls, ids, model, data):
+ pool = Pool()
+ if model in {'sale.sale', 'sale.point.sale'}:
+ Sale = pool.get(model)
+ sales = Sale.browse(ids)
+ ids = [
+ g.id for s in sales
+ for line in s.lines
+ for g in line.gift_cards]
+ model = 'sale.gift_card'
+ return super()._get_records(ids, model, data)
+
+
+class GiftCardEmail(Report):
+ __name__ = 'sale.gift_card.email'
+
+
+class GiftCard_POS(metaclass=PoolMeta):
+ __name__ = 'sale.gift_card'
+
+ @classmethod
+ def _get_origin(cls):
+ return super()._get_origin() + ['sale.point.sale.line']
+
+ @fields.depends('origin')
+ def on_change_origin(self):
+ pool = Pool()
+ POSLine = pool.get('sale.point.sale.line')
+ UOM = pool.get('product.uom')
+ if isinstance(self.origin, POSLine):
+ 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
+ super().on_change_origin()
+
+ @classmethod
+ def _get_spent_on(cls):
+ return super()._get_spent_on() + ['sale.point.sale']
+
+ @property
+ def _email(self):
+ pool = Pool()
+ POSLine = pool.get('sale.point.sale.line')
+ email = super()._email
+ if isinstance(self.origin, POSLine):
+ email = self.origin.gift_card_email
+ return 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',
+ })
+
+ @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 POSSale(metaclass=PoolMeta):
+ __name__ = 'sale.point.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',
+ })
+
+ @fields.depends('state', 'gift_cards')
+ def on_change_with_total(self, name=None):
+ total = super().on_change_with_total(name=name)
+ if self.state == 'open':
+ total -= sum(c.value for c in self.gift_cards)
+ return total
+
+ @classmethod
+ @Workflow.transition('done')
+ def do(cls, sales):
+ for sale in sales:
+ sale.add_return_gift_cards()
+ cls.save(sales)
+ super().do(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)
+
+ # TODO: print gift cards
+
+ 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.point.sale.line')
+ return Line(
+ sale=self,
+ product=gift_card.product,
+ quantity=-1,
+ unit=gift_card.product.default_uom,
+ unit_list_price=gift_card.value,
+ unit_gross_price=gift_card.value,
+ )
+
+
+class _LineMixin:
+ __slots__ = ()
+
+ 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),
+ },
+ 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:
+ with Transaction().set_context(company=card.company.id):
+ 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
+
+
+class Line(_LineMixin, metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+
+class POSSaleLine(_LineMixin, metaclass=PoolMeta):
+ __name__ = 'sale.point.sale.line'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ # Prevent selling goods gift card as POS does not manage shipment
+ cls.product.domain = [
+ cls.product.domain,
+ ['OR',
+ ('gift_card', '!=', True),
+ ('type', '=', 'service'),
+ ],
+ ]
+
+
+class POSPay(metaclass=PoolMeta):
+ __name__ = 'sale.point.sale.pay'
+
+ gift_card = StateView(
+ 'sale.point.sale.pay.gift_card',
+ 'sale_gift_card.sale_point_sale_pay_gift_card_view_form', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("Add", 'add_gift_card', 'tryton-ok', default=True),
+ ])
+ add_gift_card = StateTransition()
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.payment.buttons.insert(-1, Button(
+ "Gift Card", 'gift_card',
+ states={
+ 'invisible': Eval('amount', 0) >= 0,
+ },
+ validate=False))
+
+ def default_gift_card(self, fields):
+ return {
+ 'sale': self.record.id,
+ 'amount': -self.record.amount_to_pay,
+ }
+
+ def transition_add_gift_card(self):
+ self._add_gift_card().save()
+ if self.record.amount_to_pay:
+ return 'payment'
+ else:
+ self.model.process([self.record])
+ return 'end'
+
+ def _add_gift_card(self):
+ pool = Pool()
+ Line = pool.get('sale.point.sale.line')
+ return Line(
+ sale=self.record,
+ product=self.gift_card.product,
+ quantity=1,
+ unit=self.gift_card.product.default_uom,
+ unit_list_price=self.gift_card.amount,
+ unit_gross_price=self.gift_card.amount,
+ gift_card_email=self.gift_card.email,
+ )
+
+
+class POSPayGiftCard(ModelView):
+ "POS Pay - Gift Card"
+ __name__ = 'sale.point.sale.pay.gift_card'
+
+ sale = fields.Many2One('sale.point.sale', "Sale")
+ product = fields.Many2One(
+ 'product.product', "Product", required=True,
+ domain=[
+ ('salable', '=', True),
+ ('gift_card', '=', True),
+ ])
+ amount = Monetary(
+ "Amount", currency='currency', digits='currency', required=True)
+ email = fields.Char("Email")
+
+ currency = fields.Function(
+ fields.Many2One('currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ @fields.depends('sale')
+ def on_change_with_currency(self, name=None):
+ if self.sale and self.sale.company:
+ return self.sale.company.currency.id
diff --git a/modules/sale_gift_card/sale.xml b/modules/sale_gift_card/sale.xml
new file mode 100644
index 0000000000..8cf1653dbb
--- /dev/null
+++ b/modules/sale_gift_card/sale.xml
@@ -0,0 +1,169 @@
+
+
+
+
+
+ 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
+
+
+
+ Gift Cards
+ sale.gift_card
+ sale_gift_card/gift_card.fodt
+
+
+ form_print
+ sale.gift_card,-1
+
+
+
+ form_print
+ sale.sale,-1
+
+
+
+
+
+ sale.point.sale
+
+ sale_point_sale_form
+
+
+
+ sale.point.sale.line
+
+ sale_point_sale_line_form
+
+
+
+ sale.point.sale.pay.gift_card
+ form
+ sale_point_sale_pay_gift_card_form
+
+
+
+ form_print
+ sale.point.sale,-1
+
+
+
+
diff --git a/modules/sale_gift_card/setup.py b/modules/sale_gift_card/setup.py
new file mode 100755
index 0000000000..d3e1e7135c
--- /dev/null
+++ b/modules/sale_gift_card/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 find_packages, setup
+
+
+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'),
+ get_require_version('trytond_sale_point'),
+ ]
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_gift_card = trytond.modules.sale_gift_card
+ """, # noqa: E501
+ )
diff --git a/modules/sale_gift_card/stock.py b/modules/sale_gift_card/stock.py
new file mode 100644
index 0000000000..c2c02e1ace
--- /dev/null
+++ b/modules/sale_gift_card/stock.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.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={'internal_quantity'})
+ 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..4effdfa4a2
--- /dev/null
+++ b/modules/sale_gift_card/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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..96d687eca6
--- /dev/null
+++ b/modules/sale_gift_card/tests/scenario_sale_gift_card.rst
@@ -0,0 +1,199 @@
+=======================
+Sale Gift Card Scenario
+=======================
+
+Imports::
+
+ >>> import re
+ >>> from decimal import Decimal
+ >>> from proteus import Model, 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)
+
+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
+
+Print gift cards::
+
+ >>> gift_card_report = Report('sale.gift_card')
+ >>> bool(gift_card_report.execute([sale]))
+ 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/scenario_sale_point_gift_card.rst b/modules/sale_gift_card/tests/scenario_sale_point_gift_card.rst
new file mode 100644
index 0000000000..fee9bb502b
--- /dev/null
+++ b/modules/sale_gift_card/tests/scenario_sale_point_gift_card.rst
@@ -0,0 +1,223 @@
+=============================
+Sale Point Gift Card 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)
+
+Activate modules::
+
+ >>> config = activate_modules(['sale_gift_card', 'sale_point'])
+
+ >>> Account = Model.get('account.account')
+ >>> AccountConfig = Model.get('account.configuration')
+ >>> GiftCard = Model.get('sale.gift_card')
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUoM = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SaleConfig = Model.get('sale.configuration')
+ >>> Sequence = Model.get('ir.sequence')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+
+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)
+
+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_product, = template.products
+
+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.account_category = account_category
+ >>> template.gross_price = Decimal('50.0000')
+ >>> template.save()
+ >>> product, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create a payment method::
+
+ >>> payment_method = PaymentMethod(name="Cash")
+ >>> payment_method.account = accounts['cash']
+ >>> payment_method.save()
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10
+ >>> sale.save()
+ >>> sale.total
+ Decimal('500.00')
+
+Overpay::
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = payment_method
+ >>> payment.form.amount = Decimal('600.00')
+ >>> payment.execute('pay')
+
+ >>> payment.form.amount
+ Decimal('-100.00')
+
+Return change with a gift card::
+
+ >>> payment.execute('gift_card')
+ >>> payment.form.product = gift_card_product
+ >>> payment.form.amount
+ Decimal('100.00')
+ >>> payment.execute('add_gift_card')
+
+ >>> sale.state
+ 'done'
+
+Check gift card::
+
+ >>> gift_card, = GiftCard.find([])
+ >>> gift_card.value
+ Decimal('100.00')
+ >>> gift_card.currency == sale.currency
+ True
+
+Print gift card::
+
+ >>> gift_card_report = Report('sale.gift_card')
+ >>> bool(gift_card_report.execute([sale]))
+ True
+
+Post sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
+
+Make a second sale and pay with gift card::
+
+ >>> sale = Sale(point=pos)
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 5
+ >>> sale.gift_cards.append(GiftCard(gift_card.id))
+ >>> sale.save()
+ >>> sale.total
+ Decimal('150.00')
+
+Pay::
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = payment_method
+ >>> payment.execute('pay')
+
+ >>> sale.state
+ 'done'
+ >>> sale.total
+ Decimal('150.00')
+
+Check gift card::
+
+ >>> gift_card.reload()
+ >>> gift_card.spent_on == sale
+ True
+
+Post sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
diff --git a/modules/sale_gift_card/tests/test_module.py b/modules/sale_gift_card/tests/test_module.py
new file mode 100644
index 0000000000..8438dafdfa
--- /dev/null
+++ b/modules/sale_gift_card/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SaleGiftCardTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Gift Card module'
+ module = 'sale_gift_card'
+ extras = ['sale_point']
+
+
+del ModuleTestCase
diff --git a/modules/sale_gift_card/tests/test_scenario.py b/modules/sale_gift_card/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_gift_card/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_gift_card/tox.ini b/modules/sale_gift_card/tox.ini
new file mode 100644
index 0000000000..5b778946df
--- /dev/null
+++ b/modules/sale_gift_card/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_gift_card/* -m unittest discover -s tests
+ coverage report --include=./**/sale_gift_card/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..dd537bb4c6
--- /dev/null
+++ b/modules/sale_gift_card/tryton.cfg
@@ -0,0 +1,19 @@
+[tryton]
+version=6.7.0
+depends:
+ account
+ account_invoice
+ company
+ currency
+ ir
+ product
+ sale
+ stock
+extras_depend:
+ sale_point
+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..1e74242b2f
--- /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..1d96c5502e
--- /dev/null
+++ b/modules/sale_gift_card/view/gift_card_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
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..0eb2b3d786
--- /dev/null
+++ b/modules/sale_gift_card/view/move_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
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/sale_point_sale_form.xml b/modules/sale_gift_card/view/sale_point_sale_form.xml
new file mode 100644
index 0000000000..43df875400
--- /dev/null
+++ b/modules/sale_gift_card/view/sale_point_sale_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/sale_point_sale_line_form.xml b/modules/sale_gift_card/view/sale_point_sale_line_form.xml
new file mode 100644
index 0000000000..3f59b2c6ff
--- /dev/null
+++ b/modules/sale_gift_card/view/sale_point_sale_line_form.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_gift_card/view/sale_point_sale_pay_gift_card_form.xml b/modules/sale_gift_card/view/sale_point_sale_pay_gift_card_form.xml
new file mode 100644
index 0000000000..63aacee8b6
--- /dev/null
+++ b/modules/sale_gift_card/view/sale_point_sale_pay_gift_card_form.xml
@@ -0,0 +1,14 @@
+
+
+
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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_history/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_history/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_history/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_history/CHANGELOG b/modules/sale_history/CHANGELOG
new file mode 100644
index 0000000000..9755d073f4
--- /dev/null
+++ b/modules/sale_history/CHANGELOG
@@ -0,0 +1,25 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Add revision and history to subscription
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..7cb98d9830
--- /dev/null
+++ b/modules/sale_history/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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_history/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..013878e495
--- /dev/null
+++ b/modules/sale_history/__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 sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ sale.Line,
+ sale.LineTax,
+ module='sale_history', type_='model')
+ Pool.register(
+ sale.Subscription,
+ sale.SubscriptionLine,
+ module='sale_history', type_='model',
+ depends=['sale_subscription'])
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..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/bg.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/ca.po b/modules/sale_history/locale/ca.po
new file mode 100644
index 0000000000..e938ec4215
--- /dev/null
+++ b/modules/sale_history/locale/ca.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisió"
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revisió"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/cs.po b/modules/sale_history/locale/cs.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/cs.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/de.po b/modules/sale_history/locale/de.po
new file mode 100644
index 0000000000..5391068628
--- /dev/null
+++ b/modules/sale_history/locale/de.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Version"
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Version"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/es.po b/modules/sale_history/locale/es.po
new file mode 100644
index 0000000000..a7158e6b6d
--- /dev/null
+++ b/modules/sale_history/locale/es.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisión"
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revisión"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+msgctxt "view:sale.subscription:"
+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..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/es_419.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/et.po b/modules/sale_history/locale/et.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/et.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/fa.po b/modules/sale_history/locale/fa.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/fa.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/fi.po b/modules/sale_history/locale/fi.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/fi.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/fr.po b/modules/sale_history/locale/fr.po
new file mode 100644
index 0000000000..edd5487342
--- /dev/null
+++ b/modules/sale_history/locale/fr.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Révision"
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Révision"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/hu.po b/modules/sale_history/locale/hu.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/hu.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/id.po b/modules/sale_history/locale/id.po
new file mode 100644
index 0000000000..bcf4254941
--- /dev/null
+++ b/modules/sale_history/locale/id.po
@@ -0,0 +1,21 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisi"
+
+#, fuzzy
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revisi"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/it.po b/modules/sale_history/locale/it.po
new file mode 100644
index 0000000000..bf72571a0e
--- /dev/null
+++ b/modules/sale_history/locale/it.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisione"
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revisione"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/lo.po b/modules/sale_history/locale/lo.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/lo.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/lt.po b/modules/sale_history/locale/lt.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/lt.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/nl.po b/modules/sale_history/locale/nl.po
new file mode 100644
index 0000000000..6a53a351ad
--- /dev/null
+++ b/modules/sale_history/locale/nl.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Herziening"
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revisie"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/pl.po b/modules/sale_history/locale/pl.po
new file mode 100644
index 0000000000..fd7dd5be27
--- /dev/null
+++ b/modules/sale_history/locale/pl.po
@@ -0,0 +1,21 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Wersja"
+
+#, fuzzy
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Wersja"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/pt.po b/modules/sale_history/locale/pt.po
new file mode 100644
index 0000000000..c675340e5c
--- /dev/null
+++ b/modules/sale_history/locale/pt.po
@@ -0,0 +1,20 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revisão"
+
+#, fuzzy
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revisão"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/ro.po b/modules/sale_history/locale/ro.po
new file mode 100644
index 0000000000..cf9047a657
--- /dev/null
+++ b/modules/sale_history/locale/ro.po
@@ -0,0 +1,21 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr "Revizuire"
+
+#, fuzzy
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr "Revizuire"
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr "/"
+
+#, fuzzy
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr "/"
diff --git a/modules/sale_history/locale/ru.po b/modules/sale_history/locale/ru.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/ru.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/sl.po b/modules/sale_history/locale/sl.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/sl.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/tr.po b/modules/sale_history/locale/tr.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/tr.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/locale/uk.po b/modules/sale_history/locale/uk.po
new file mode 100644
index 0000000000..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/uk.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+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..6b7f3c20bd
--- /dev/null
+++ b/modules/sale_history/locale/zh_CN.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "field:sale.subscription,revision:"
+msgid "Revision"
+msgstr ""
+
+msgctxt "view:sale.sale:"
+msgid "/"
+msgstr ""
+
+msgctxt "view:sale.subscription:"
+msgid "/"
+msgstr ""
diff --git a/modules/sale_history/sale.py b/modules/sale_history/sale.py
new file mode 100644
index 0000000000..79e27195d0
--- /dev/null
+++ b/modules/sale_history/sale.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 ModelView, Workflow, fields
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval
+from trytond.tools import grouped_slice, reduce_ids
+from trytond.transaction import Transaction
+
+
+class RevisionMixin:
+ __slots__ = ()
+ 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, records, default=None):
+ default = default.copy() if default is not None else {}
+ default.setdefault('revision', cls.default_revision())
+ return super().copy(records, default=default)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('draft')
+ def draft(cls, records):
+ cursor = Transaction().connection.cursor()
+ table = cls.__table__()
+
+ # Use SQL and before super to avoid two history entries
+ for sub_records in grouped_slice(records):
+ cursor.execute(*table.update(
+ [table.revision],
+ [table.revision + 1],
+ where=reduce_ids(table.id, sub_records)))
+
+ super().draft(records)
+
+
+class Sale(RevisionMixin, metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+ _history = True
+
+
+class Line(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+ _history = True
+
+
+class LineTax(metaclass=PoolMeta):
+ __name__ = 'sale.line-account.tax'
+ _history = True
+
+
+class Subscription(RevisionMixin, metaclass=PoolMeta):
+ __name__ = 'sale.subscription'
+ _history = True
+
+
+class SubscriptionLine(metaclass=PoolMeta):
+ __name__ = 'sale.subscription.line'
+ _history = True
diff --git a/modules/sale_history/sale.xml b/modules/sale_history/sale.xml
new file mode 100644
index 0000000000..cf9eb72942
--- /dev/null
+++ b/modules/sale_history/sale.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+ sale.sale
+
+ sale_form
+
+
+ sale.sale
+
+ sale_tree
+
+
+
+
+ sale.subscription
+
+ sale_form
+
+
+ sale.subscription
+
+ sale_tree
+
+
+
+
diff --git a/modules/sale_history/setup.py b/modules/sale_history/setup.py
new file mode 100755
index 0000000000..564c57a5db
--- /dev/null
+++ b/modules/sale_history/setup.py
@@ -0,0 +1,152 @@
+#!/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 find_packages, setup
+
+
+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'),
+ get_require_version('trytond_sale_subscription'),
+ ]
+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',
+ 'Natural Language :: Turkish',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_history = trytond.modules.sale_history
+ """,
+ )
diff --git a/modules/sale_history/tests/__init__.py b/modules/sale_history/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_history/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_history/tests/test_module.py
new file mode 100644
index 0000000000..bd291af439
--- /dev/null
+++ b/modules/sale_history/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleHistoryTestCase(ModuleTestCase):
+ 'Test Sale History module'
+ module = 'sale_history'
+ extras = ['sale_subscription']
+
+
+del ModuleTestCase
diff --git a/modules/sale_history/tests/test_scenario.py b/modules/sale_history/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_history/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_history/tox.ini b/modules/sale_history/tox.ini
new file mode 100644
index 0000000000..5ef0e97276
--- /dev/null
+++ b/modules/sale_history/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_history/* -m unittest discover -s tests
+ coverage report --include=./**/sale_history/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..8443c13c46
--- /dev/null
+++ b/modules/sale_history/tryton.cfg
@@ -0,0 +1,9 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ sale
+extras_depend:
+ sale_subscription
+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_date/.drone.yml b/modules/sale_invoice_date/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale_invoice_date/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_invoice_date/.flake8 b/modules/sale_invoice_date/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_invoice_date/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_invoice_date/.isort.cfg b/modules/sale_invoice_date/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_invoice_date/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_invoice_date/CHANGELOG b/modules/sale_invoice_date/CHANGELOG
new file mode 100644
index 0000000000..7a287d58a2
--- /dev/null
+++ b/modules/sale_invoice_date/CHANGELOG
@@ -0,0 +1,7 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+--------------------------
+* Initial release
diff --git a/modules/sale_invoice_date/COPYRIGHT b/modules/sale_invoice_date/COPYRIGHT
new file mode 100644
index 0000000000..48e43c6ea0
--- /dev/null
+++ b/modules/sale_invoice_date/COPYRIGHT
@@ -0,0 +1,14 @@
+Copyright (C) 2021-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_invoice_date/LICENSE b/modules/sale_invoice_date/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_invoice_date/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_date/MANIFEST.in b/modules/sale_invoice_date/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_invoice_date/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_invoice_date/README.rst b/modules/sale_invoice_date/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_invoice_date/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_invoice_date/__init__.py b/modules/sale_invoice_date/__init__.py
new file mode 100644
index 0000000000..2fa103536c
--- /dev/null
+++ b/modules/sale_invoice_date/__init__.py
@@ -0,0 +1,20 @@
+# 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, sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.InvoiceTerm,
+ sale.InvoiceTermRelativeDelta,
+ sale.Configuration,
+ sale.ConfigurationSaleMethod,
+ sale.Sale,
+ party.Party,
+ party.PartySaleMethod,
+ module='sale_invoice_date', type_='model')
diff --git a/modules/sale_invoice_date/doc/conf.py b/modules/sale_invoice_date/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_invoice_date/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_invoice_date/doc/design.rst b/modules/sale_invoice_date/doc/design.rst
new file mode 100644
index 0000000000..090d6c4f24
--- /dev/null
+++ b/modules/sale_invoice_date/doc/design.rst
@@ -0,0 +1,37 @@
+******
+Design
+******
+
+The *Sale Invoice Date Module* introduces some new concepts and extends
+existing concepts.
+
+.. _model-sale.invoice.term:
+
+Invoice Term
+============
+
+The *Invoice Term* stores the method used to calculate the date of the invoice
+based on the moment the invoice is created.
+
+.. seealso::
+
+ Invoice terms are created and managed from the main menu item:
+
+ |Sales --> Configuration --> Invoice Terms|__
+
+ .. |Sales --> Configuration --> Invoice Terms| replace:: :menuselection:`Sales --> Configuration --> Invoice Terms`
+ __ https://demo.tryton.org/model/sale.invoice.term
+
+.. _model-sale.sale:
+
+Sale
+====
+
+The *Sale* concept is extended to store the `Invoice Term
+` from the `Party ` or the
+`Configuration `.
+
+.. seealso::
+
+ The `Sale ` concept is introduced by the :doc:`Sale
+ Module `.
diff --git a/modules/sale_invoice_date/doc/index.rst b/modules/sale_invoice_date/doc/index.rst
new file mode 100644
index 0000000000..bff9f7b6c8
--- /dev/null
+++ b/modules/sale_invoice_date/doc/index.rst
@@ -0,0 +1,11 @@
+########################
+Sale Invoice Date Module
+########################
+
+The *Sale Invoice Date Module* fills the invoice date of invoices created by sales.
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ releases
diff --git a/modules/sale_invoice_date/doc/releases.rst b/modules/sale_invoice_date/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_invoice_date/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_invoice_date/locale/bg.po b/modules/sale_invoice_date/locale/bg.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/bg.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/ca.po b/modules/sale_invoice_date/locale/ca.po
new file mode 100644
index 0000000000..80b8ea772d
--- /dev/null
+++ b/modules/sale_invoice_date/locale/ca.po
@@ -0,0 +1,87 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termini de facturació venta"
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termini de facturació venta"
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termini de facturació venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termini de facturació venta"
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr "Increments"
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr "Dia del mes"
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr "Nombre de dies"
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr "Nombre de mesos"
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr "Termini de facturació"
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr "Dia de la setmana"
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr "Nombre de setmanes"
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr "Termini de facturació"
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"El termini de facturació de venta per defecte pel client.\n"
+"Deixeu-ho en blanc per utilitzar el valor per defecte de la configuració."
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr "L'identificador principal del termini de facturació."
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Terminis de facturació"
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Terminis de facturació"
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr "Termini de facturació"
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr "Increment del termini de facturació"
diff --git a/modules/sale_invoice_date/locale/cs.po b/modules/sale_invoice_date/locale/cs.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/cs.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/de.po b/modules/sale_invoice_date/locale/de.po
new file mode 100644
index 0000000000..d275d7833f
--- /dev/null
+++ b/modules/sale_invoice_date/locale/de.po
@@ -0,0 +1,87 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkauf Rechnungskonditionen"
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkauf Rechnungskonditionen"
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkauf Rechnungskonditionen"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkauf Rechnungskondition"
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr "Zeitspannen"
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr "Tag des Monats"
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr "Anzahl an Tagen"
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr "Monat"
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr "Anzahl an Monaten"
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr "Rechnungskonditionen"
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr "Wochentag"
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr "Anzahl an Wochen"
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr "Rechnungskonditionen"
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"Die Standardrechnungskonditionen für den Kunden.\n"
+"Leer lassen um den Standardwert aus der Konfiguration zu verwenden."
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr "Das Hauptidentifizierungsmerkmal der Rechnungskonditionen."
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Rechnungskonditionen"
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Rechnungskonditionen"
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr "Rechnungskonditionen"
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr "Rechnungskondition Zeitspanne"
diff --git a/modules/sale_invoice_date/locale/es.po b/modules/sale_invoice_date/locale/es.po
new file mode 100644
index 0000000000..9eaaa9c365
--- /dev/null
+++ b/modules/sale_invoice_date/locale/es.po
@@ -0,0 +1,87 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Plazo facturación venta"
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Plazo facturación venta"
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Plazo facturación venta"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Plazo facturación venta"
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr "Incrementos"
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr "Día del mes"
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr "Número de días"
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr "Número de meses"
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr "Plazo de facturación"
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr "Día de la semana"
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr "Número de semanas"
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr "Plazo de facturación"
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"El plazo de facturación de venta por defecto para el cliente.\n"
+"Dejar vacío para utilizar el valor por defecto de la configuración."
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr "El identificador principal del plazo de facturación."
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Plazos de facturación"
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Plazos de facturación"
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr "Plazo de facturación"
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr "Incremento del plazo de facturación"
diff --git a/modules/sale_invoice_date/locale/es_419.po b/modules/sale_invoice_date/locale/es_419.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/es_419.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/et.po b/modules/sale_invoice_date/locale/et.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/et.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/fa.po b/modules/sale_invoice_date/locale/fa.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/fa.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/fi.po b/modules/sale_invoice_date/locale/fi.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/fi.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/fr.po b/modules/sale_invoice_date/locale/fr.po
new file mode 100644
index 0000000000..88915ca435
--- /dev/null
+++ b/modules/sale_invoice_date/locale/fr.po
@@ -0,0 +1,87 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Condition de facturation de vente"
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Condition de facturation de vente"
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Condition de facturation de vente"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Condition de facturation de vente"
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr "Deltas"
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr "Jour du mois"
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr "Nombre de jours"
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr "Mois"
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr "Nombre de mois"
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr "Condition de facturation"
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr "Jour de la semaine"
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr "Nombre de semaines"
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr "Condition de facturation"
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"La condition de facturation de vente par défaut pour le client.\n"
+"Laissez vide pour utiliser la valeur par défaut de la configuration."
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr "L'identifiant principal de la condition de facturation."
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Conditions de facturation"
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Conditions de facturation"
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr "Condition de facturation"
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr "Delta de condition de facturation"
diff --git a/modules/sale_invoice_date/locale/hu.po b/modules/sale_invoice_date/locale/hu.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/hu.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/id.po b/modules/sale_invoice_date/locale/id.po
new file mode 100644
index 0000000000..67c4ec7769
--- /dev/null
+++ b/modules/sale_invoice_date/locale/id.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr "Bulan"
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/it.po b/modules/sale_invoice_date/locale/it.po
new file mode 100644
index 0000000000..78d0fab53e
--- /dev/null
+++ b/modules/sale_invoice_date/locale/it.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termine di fatturazione della vendita"
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termine di fatturazione della vendita"
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termine di fatturazione della vendita"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Termine di fatturazione della vendita"
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Nome"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/lo.po b/modules/sale_invoice_date/locale/lo.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/lo.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/lt.po b/modules/sale_invoice_date/locale/lt.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/lt.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/nl.po b/modules/sale_invoice_date/locale/nl.po
new file mode 100644
index 0000000000..9f2d768e0a
--- /dev/null
+++ b/modules/sale_invoice_date/locale/nl.po
@@ -0,0 +1,87 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkoopfactuur termijn"
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkoopfactuur termijn"
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkoopfactuur termijn"
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr "Verkoopfactuur termijn"
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr "Verschillen"
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr "Dag van de maand"
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr "Aantal dagen"
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr "Maand"
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr "Aantal maanden"
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr "Factuur termijn"
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr "Dag van de week"
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr "Aantal weken"
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr "Factuur termijn"
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+"De standaard factuur termijn voor de klant.\n"
+"Laat leeg om de standaard waarde te gebruiken van de configuratie."
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr "De hoofd identificatie van de factuur termijn."
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Factuur termijnen"
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr "Factuur termijnen"
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr "Factuur termijn"
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr "Factuur termijn verschillen"
diff --git a/modules/sale_invoice_date/locale/pl.po b/modules/sale_invoice_date/locale/pl.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/pl.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/pt.po b/modules/sale_invoice_date/locale/pt.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/pt.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/ro.po b/modules/sale_invoice_date/locale/ro.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/ro.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/ru.po b/modules/sale_invoice_date/locale/ru.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/ru.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/sl.po b/modules/sale_invoice_date/locale/sl.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/sl.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/tr.po b/modules/sale_invoice_date/locale/tr.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/tr.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/uk.po b/modules/sale_invoice_date/locale/uk.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/uk.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/locale/zh_CN.po b/modules/sale_invoice_date/locale/zh_CN.po
new file mode 100644
index 0000000000..31b36c41d7
--- /dev/null
+++ b/modules/sale_invoice_date/locale/zh_CN.po
@@ -0,0 +1,85 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:party.party,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:party.party.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.configuration.sale_method,sale_invoice_term:"
+msgid "Sale Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.invoice.term,relative_deltas:"
+msgid "Deltas"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,day:"
+msgid "Day of Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,days:"
+msgid "Number of Days"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,month:"
+msgid "Month"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,months:"
+msgid "Number of Months"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weekday:"
+msgid "Day of Week"
+msgstr ""
+
+msgctxt "field:sale.invoice.term.relative_delta,weeks:"
+msgid "Number of Weeks"
+msgstr ""
+
+msgctxt "field:sale.sale,invoice_term:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "help:party.party,sale_invoice_term:"
+msgid ""
+"The default sale invoice term for the customer.\n"
+"Leave empty to use the default value from the configuration."
+msgstr ""
+
+msgctxt "help:sale.invoice.term,name:"
+msgid "The main identifier of the invoice term."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_invoice_term_form"
+msgid "Invoice Terms"
+msgstr ""
+
+msgctxt "model:sale.invoice.term,name:"
+msgid "Invoice Term"
+msgstr ""
+
+msgctxt "model:sale.invoice.term.relative_delta,name:"
+msgid "Invoice Term Delta"
+msgstr ""
diff --git a/modules/sale_invoice_date/party.py b/modules/sale_invoice_date/party.py
new file mode 100644
index 0000000000..a3105c26b8
--- /dev/null
+++ b/modules/sale_invoice_date/party.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 trytond.model import fields
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
+
+
+class Party(metaclass=PoolMeta):
+ __name__ = 'party.party'
+
+ sale_invoice_term = fields.MultiValue(fields.Many2One(
+ 'sale.invoice.term', "Sale Invoice Term",
+ help="The default sale invoice term for the customer.\n"
+ "Leave empty to use the default value from the configuration."))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'sale_invoice_term':
+ return pool.get('party.party.sale_method')
+ return super().multivalue_model(field)
+
+ @classmethod
+ def copy(cls, parties, default=None):
+ context = Transaction().context
+ default = default.copy() if default else {}
+ if context.get('_check_access'):
+ default_values = cls.default_get(
+ ['sale_invoice_term'], with_rec_name=False)
+ default.setdefault(
+ 'sale_invoice_term', default_values.get('sale_invoice_term'))
+ return super().copy(parties, default=default)
+
+
+class PartySaleMethod(metaclass=PoolMeta):
+ __name__ = 'party.party.sale_method'
+
+ sale_invoice_term = fields.Many2One(
+ 'sale.invoice.term', "Sale Invoice Term", ondelete='RESTRICT')
diff --git a/modules/sale_invoice_date/party.xml b/modules/sale_invoice_date/party.xml
new file mode 100644
index 0000000000..eb27aadfd3
--- /dev/null
+++ b/modules/sale_invoice_date/party.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ party.party
+
+ party_form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_date/sale.py b/modules/sale_invoice_date/sale.py
new file mode 100644
index 0000000000..cb92ea5567
--- /dev/null
+++ b/modules/sale_invoice_date/sale.py
@@ -0,0 +1,133 @@
+# 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.relativedelta import relativedelta
+
+from trytond.model import (
+ DeactivableMixin, ModelSQL, ModelView, fields, sequence_ordered)
+from trytond.pool import Pool, PoolMeta
+
+
+class InvoiceTerm(DeactivableMixin, ModelSQL, ModelView):
+ "Invoice Term"
+ __name__ = 'sale.invoice.term'
+
+ name = fields.Char(
+ "Name", required=True, translate=True,
+ help="The main identifier of the invoice term.")
+ relative_deltas = fields.One2Many(
+ 'sale.invoice.term.relative_delta', 'term', "Deltas")
+
+ def get_date(self, date=None):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ if date is None:
+ date = Date.today()
+ for relative_delta in self.relative_deltas:
+ date += relative_delta.get()
+ return date
+
+
+class InvoiceTermRelativeDelta(sequence_ordered(), ModelSQL, ModelView):
+ "Invoice Term Delta"
+ __name__ = 'sale.invoice.term.relative_delta'
+
+ term = fields.Many2One(
+ 'sale.invoice.term', "Invoice Term", required=True, ondelete='CASCADE')
+ day = fields.Integer('Day of Month',
+ domain=['OR',
+ ('day', '=', None),
+ [('day', '>=', 1), ('day', '<=', 31)],
+ ])
+ month = fields.Many2One('ir.calendar.month', "Month")
+ weekday = fields.Many2One('ir.calendar.day', "Day of Week")
+ months = fields.Integer('Number of Months', required=True)
+ weeks = fields.Integer('Number of Weeks', required=True)
+ days = fields.Integer('Number of Days', required=True)
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('term')
+
+ @classmethod
+ def default_months(cls):
+ return 0
+
+ @classmethod
+ def default_weeks(cls):
+ return 0
+
+ @classmethod
+ def default_days(cls):
+ return 0
+
+ def get(self):
+ "Return the relativedelta"
+ return relativedelta(
+ day=self.day,
+ month=int(self.month.index) if self.month else None,
+ days=self.days,
+ weeks=self.weeks,
+ months=self.months,
+ weekday=int(self.weekday.index) if self.weekday else None,
+ )
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ sale_invoice_term = fields.MultiValue(fields.Many2One(
+ 'sale.invoice.term', "Sale Invoice Term"))
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'sale_invoice_term':
+ return pool.get('sale.configuration.sale_method')
+ return super().multivalue_model(field)
+
+
+class ConfigurationSaleMethod(metaclass=PoolMeta):
+ __name__ = 'sale.configuration.sale_method'
+
+ sale_invoice_term = fields.Many2One(
+ 'sale.invoice.term', "Sale Invoice Term")
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ invoice_term = fields.Many2One(
+ 'sale.invoice.term', "Invoice Term", ondelete='RESTRICT')
+
+ @classmethod
+ def default_invoice_term(cls, **pattern):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ config = Configuration(1)
+ invoice_term = config.get_multivalue('sale_invoice_term', **pattern)
+ return invoice_term.id if invoice_term else None
+
+ @fields.depends('party', 'company')
+ def on_change_party(self):
+ super().on_change_party()
+ self.invoice_term = self.default_invoice_term(
+ company=self.company.id if self.company else None)
+ if self.party:
+ if self.party.sale_invoice_term:
+ self.invoice_term = self.party.sale_invoice_term
+
+ @property
+ def _invoice_term_date(self):
+ return
+
+ def _get_invoice_sale(self):
+ invoice = super()._get_invoice_sale()
+ if self.invoice_term:
+ invoice.invoice_date = self.invoice_term.get_date(
+ date=self._invoice_term_date)
+ return invoice
+
+ @property
+ def _invoice_grouping_fields(self):
+ return super()._invoice_grouping_fields + ('invoice_date',)
diff --git a/modules/sale_invoice_date/sale.xml b/modules/sale_invoice_date/sale.xml
new file mode 100644
index 0000000000..89341c06fc
--- /dev/null
+++ b/modules/sale_invoice_date/sale.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+ sale.invoice.term
+ form
+ invoice_term_form
+
+
+
+ sale.invoice.term
+ tree
+ invoice_term_list
+
+
+
+ Invoice Terms
+ sale.invoice.term
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.invoice.term.relative_delta
+ form
+ invoice_term_relative_delta_form
+
+
+
+ sale.invoice.term.relative_delta
+ tree
+ invoice_term_relative_delta_list
+
+
+
+ sale.invoice.term.relative_delta
+ tree
+ invoice_term_relative_delta_list_sequence
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
diff --git a/modules/sale_invoice_date/setup.py b/modules/sale_invoice_date/setup.py
new file mode 100755
index 0000000000..52a0b8e829
--- /dev/null
+++ b/modules/sale_invoice_date/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 find_packages, setup
+
+
+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_invoice_date'
+
+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 to compute invoice date of 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-invoice-date'),
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_invoice_date',
+ },
+ keywords='tryton sale invoice date',
+ package_dir={'trytond.modules.sale_invoice_date': '.'},
+ packages=(
+ ['trytond.modules.sale_invoice_date']
+ + ['trytond.modules.sale_invoice_date.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_invoice_date': (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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_invoice_date = trytond.modules.sale_invoice_date
+ """, # noqa: E501
+ )
diff --git a/modules/sale_invoice_date/tests/__init__.py b/modules/sale_invoice_date/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_invoice_date/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_invoice_date/tests/scenario_sale_invoice_date.rst b/modules/sale_invoice_date/tests/scenario_sale_invoice_date.rst
new file mode 100644
index 0000000000..eb733c5952
--- /dev/null
+++ b/modules/sale_invoice_date/tests/scenario_sale_invoice_date.rst
@@ -0,0 +1,102 @@
+==========================
+Sale Invoice Date Scenario
+==========================
+
+Imports::
+
+ >>> import datetime as dt
+ >>> 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)
+
+ >>> today = dt.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('sale_invoice_date')
+
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> InvoiceTerm = Model.get('sale.invoice.term')
+ >>> Sale = Model.get('sale.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)
+
+Create invoice term::
+
+ >>> invoice_term = InvoiceTerm(name="End of Month")
+ >>> relative_delta = invoice_term.relative_deltas.new()
+ >>> relative_delta.day = 31
+ >>> invoice_term.save()
+
+Create parties::
+
+ >>> customer = Party(name="Customer")
+ >>> customer.sale_invoice_term = invoice_term
+ >>> customer.save()
+
+Create account categories::
+
+ >>> 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::
+
+ >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+
+ >>> 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
+
+Make a sale::
+
+ >>> sale = Sale(party=customer)
+ >>> sale.invoice_term == invoice_term
+ True
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'processing'
+
+Check invoice date::
+
+ >>> invoice, = sale.invoices
+ >>> invoice.invoice_date == today + relativedelta(day=31)
+ True
diff --git a/modules/sale_invoice_date/tests/test_module.py b/modules/sale_invoice_date/tests/test_module.py
new file mode 100644
index 0000000000..9338e4e3cb
--- /dev/null
+++ b/modules/sale_invoice_date/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleInvoiceDateTestCase(ModuleTestCase):
+ 'Test Sale Invoice Date module'
+ module = 'sale_invoice_date'
+
+
+del ModuleTestCase
diff --git a/modules/sale_invoice_date/tests/test_scenario.py b/modules/sale_invoice_date/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_invoice_date/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_invoice_date/tox.ini b/modules/sale_invoice_date/tox.ini
new file mode 100644
index 0000000000..f16d41a030
--- /dev/null
+++ b/modules/sale_invoice_date/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale/* -m unittest discover -s tests
+ coverage report --include=./**/sale/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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_date/tryton.cfg b/modules/sale_invoice_date/tryton.cfg
new file mode 100644
index 0000000000..c39b88d775
--- /dev/null
+++ b/modules/sale_invoice_date/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ sale
+ party
+extras_depend:
+ sale_invoice_grouping
+xml:
+ sale.xml
+ party.xml
diff --git a/modules/sale_invoice_date/view/configuration_form.xml b/modules/sale_invoice_date/view/configuration_form.xml
new file mode 100644
index 0000000000..ee6bba60fb
--- /dev/null
+++ b/modules/sale_invoice_date/view/configuration_form.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_date/view/invoice_term_form.xml b/modules/sale_invoice_date/view/invoice_term_form.xml
new file mode 100644
index 0000000000..feec283f96
--- /dev/null
+++ b/modules/sale_invoice_date/view/invoice_term_form.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/modules/sale_invoice_date/view/invoice_term_list.xml b/modules/sale_invoice_date/view/invoice_term_list.xml
new file mode 100644
index 0000000000..b4d89538b1
--- /dev/null
+++ b/modules/sale_invoice_date/view/invoice_term_list.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/modules/sale_invoice_date/view/invoice_term_relative_delta_form.xml b/modules/sale_invoice_date/view/invoice_term_relative_delta_form.xml
new file mode 100644
index 0000000000..1ecebb830d
--- /dev/null
+++ b/modules/sale_invoice_date/view/invoice_term_relative_delta_form.xml
@@ -0,0 +1,24 @@
+
+
+
diff --git a/modules/sale_invoice_date/view/invoice_term_relative_delta_list.xml b/modules/sale_invoice_date/view/invoice_term_relative_delta_list.xml
new file mode 100644
index 0000000000..9d6374f677
--- /dev/null
+++ b/modules/sale_invoice_date/view/invoice_term_relative_delta_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_date/view/invoice_term_relative_delta_list_sequence.xml b/modules/sale_invoice_date/view/invoice_term_relative_delta_list_sequence.xml
new file mode 100644
index 0000000000..8e3c17d67b
--- /dev/null
+++ b/modules/sale_invoice_date/view/invoice_term_relative_delta_list_sequence.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_date/view/party_form.xml b/modules/sale_invoice_date/view/party_form.xml
new file mode 100644
index 0000000000..b0db2d8cba
--- /dev/null
+++ b/modules/sale_invoice_date/view/party_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_date/view/sale_form.xml b/modules/sale_invoice_date/view/sale_form.xml
new file mode 100644
index 0000000000..95d0648e37
--- /dev/null
+++ b/modules/sale_invoice_date/view/sale_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_invoice_grouping/.drone.yml b/modules/sale_invoice_grouping/.drone.yml
new file mode 100644
index 0000000000..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_invoice_grouping/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_invoice_grouping/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_invoice_grouping/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_invoice_grouping/CHANGELOG b/modules/sale_invoice_grouping/CHANGELOG
new file mode 100644
index 0000000000..8ca9fe6720
--- /dev/null
+++ b/modules/sale_invoice_grouping/CHANGELOG
@@ -0,0 +1,63 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..ac8aaac9e8
--- /dev/null
+++ b/modules/sale_invoice_grouping/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2013-2017 Nicolas Évrard.
+Copyright (C) 2013-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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_invoice_grouping/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..f9997511b9
--- /dev/null
+++ b/modules/sale_invoice_grouping/__init__.py
@@ -0,0 +1,16 @@
+# 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, party, sale
+
+
+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..6fdaee31d0
--- /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 "Controparte"
+
+#, 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/uk.po b/modules/sale_invoice_grouping/locale/uk.po
new file mode 100644
index 0000000000..54a581e066
--- /dev/null
+++ b/modules/sale_invoice_grouping/locale/uk.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..7b22e657d6
--- /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 Pool, PoolMeta
+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')
+ 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..3bcac4054a
--- /dev/null
+++ b/modules/sale_invoice_grouping/sale.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 itertools import groupby
+
+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
+
+ @classmethod
+ def _process_invoice(cls, sales):
+ for method, sales in groupby(
+ sales, lambda s: s.invoice_grouping_method):
+ if method:
+ for sale in sales:
+ super()._process_invoice([sale])
+ else:
+ super()._process_invoice(list(sales))
diff --git a/modules/sale_invoice_grouping/setup.py b/modules/sale_invoice_grouping/setup.py
new file mode 100755
index 0000000000..b35042d74f
--- /dev/null
+++ b/modules/sale_invoice_grouping/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_invoice_grouping = trytond.modules.sale_invoice_grouping
+ """,
+ )
diff --git a/modules/sale_invoice_grouping/tests/__init__.py b/modules/sale_invoice_grouping/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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/scenario_sale_invoice_grouping_multiple.rst b/modules/sale_invoice_grouping/tests/scenario_sale_invoice_grouping_multiple.rst
new file mode 100644
index 0000000000..ddb9db3627
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/scenario_sale_invoice_grouping_multiple.rst
@@ -0,0 +1,103 @@
+=======================================
+Sale Invoice Grouping Multiple 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_invoice_grouping')
+
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductUom = Model.get('product.uom')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> Sale = Model.get('sale.sale')
+ >>> Invoice = Model.get('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)
+
+Create parties::
+
+ >>> customer = Party(
+ ... name="Customer",
+ ... sale_invoice_grouping_method='standard')
+ >>> 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('10')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> product, = template.products
+
+Sale some products::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.invoice_method = 'order'
+ >>> sale_line = sale.lines.new()
+ >>> sale_line.product = product
+ >>> sale_line.quantity = 2.0
+ >>> sale.click('quote')
+ >>> sales = [sale]
+
+Make another sale::
+
+ >>> sale, = Sale.duplicate([sale])
+ >>> sale.click('quote')
+ >>> sales.append(sale)
+
+Confirm both sales::
+
+ >>> Sale.click(sales, 'confirm')
+ >>> state, = set(s.state for s in sales)
+ >>> state
+ 'processing'
+
+Check the invoices::
+
+ >>> invoice, = Invoice.find([('party', '=', customer.id)])
+
+Deleting the invoice keeps same grouping::
+
+ >>> invoice.delete()
+ >>> invoice, = Invoice.find([('party', '=', customer.id)])
diff --git a/modules/sale_invoice_grouping/tests/test_module.py b/modules/sale_invoice_grouping/tests/test_module.py
new file mode 100644
index 0000000000..a54f1591c5
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleInvoiceGroupingTestCase(ModuleTestCase):
+ 'Test Sale Invoice Grouping module'
+ module = 'sale_invoice_grouping'
+
+
+del ModuleTestCase
diff --git a/modules/sale_invoice_grouping/tests/test_scenario.py b/modules/sale_invoice_grouping/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_invoice_grouping/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_invoice_grouping/tox.ini b/modules/sale_invoice_grouping/tox.ini
new file mode 100644
index 0000000000..e4711df1bd
--- /dev/null
+++ b/modules/sale_invoice_grouping/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_invoice_grouping/* -m unittest discover -s tests
+ coverage report --include=./**/sale_invoice_grouping/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..cdc6325fad
--- /dev/null
+++ b/modules/sale_invoice_grouping/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.7.0
+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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_opportunity/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_opportunity/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_opportunity/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_opportunity/CHANGELOG b/modules/sale_opportunity/CHANGELOG
new file mode 100644
index 0000000000..21b03be7ed
--- /dev/null
+++ b/modules/sale_opportunity/CHANGELOG
@@ -0,0 +1,105 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Refactor reporting
+* Use default customer payment term
+* Allow to store currency on opportunity
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Use Date field for monthly report
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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..e49ec37516
--- /dev/null
+++ b/modules/sale_opportunity/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2010-2011 Open Labs Business Solutions.
+Copyright (C) 2010-2022 Cédric Krier.
+Copyright (C) 2010-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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_opportunity/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
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..d202bb38a5
--- /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 (
+ account, company, configuration, opportunity, opportunity_reporting, party,
+ product, sale)
+
+
+def register():
+ Pool.register(
+ opportunity.SaleOpportunity,
+ opportunity.SaleOpportunityLine,
+ opportunity_reporting.Context,
+ opportunity_reporting.Main,
+ opportunity_reporting.MainTimeseries,
+ opportunity_reporting.Conversion,
+ opportunity_reporting.ConversionTimeseries,
+ opportunity_reporting.ConversionEmployee,
+ opportunity_reporting.ConversionEmployeeTimeseries,
+ 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..d4c51df144
--- /dev/null
+++ b/modules/sale_opportunity/configuration.py
@@ -0,0 +1,71 @@
+# 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.pool import Pool, PoolMeta
+from trytond.pyson import Eval, Id
+
+
+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')),
+ ])
+
+ @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..c89698c347
--- /dev/null
+++ b/modules/sale_opportunity/locale/bg.po
@@ -0,0 +1,588 @@
+#
+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,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 "Единица"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Фирма"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Начална дата"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Крайна дата"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Служител"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Възможност"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Възможност"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Възможност"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Възможност"
+
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Обменен курс"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Обменен курс"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Конвертиран"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Конвертирана сума"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Конвертирана сума"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Изгубен"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Възможност"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Номер"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Уон"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Сума"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Възможност"
+
+#, 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 "Ред от възможност за продажба"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Възможност за продажба за служител за месец"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Възможност за продажа по месец"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Възможност за продажба за служител"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Възможност за продажба за служител"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Възможност за продажа по месец"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Ред от възможност за продажба"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+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 "Уон"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Месец"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Година"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Изгубен"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Уон"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Изгубен"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Уон"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Изгубен"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Уон"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Конвертиран"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Конвертирана сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Конвертиран"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Конвертирана сума"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Инициатива/Възможност"
diff --git a/modules/sale_opportunity/locale/ca.po b/modules/sale_opportunity/locale/ca.po
new file mode 100644
index 0000000000..e32bb69263
--- /dev/null
+++ b/modules/sale_opportunity/locale/ca.po
@@ -0,0 +1,517 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Des de la data"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr "Període"
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Fins a la data"
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Conversió d'oportunitats"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Conversió d'oportunitats per empleat"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Conversió d'oportunitats per empleat"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Conversió d'oportunitats"
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Oportunitats"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Oportunitats"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Tendènciaimport"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Rati conversió"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Tendència conversió"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Convertides"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Import convertides"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Tendència import convertides"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Número d'oportunitats"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Tendència número"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Rati guanyades"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Tendència guanyades"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Tendència import guanyades"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Iniciatives i oportunitats"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Oportunitats"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Context informe d'oportunitats"
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Informe de conversions d'oportunitats"
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Informe de conversions d'oportunitats per empleat"
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Informe de conversions d'oportunitats per empleat"
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Informe de conversions d'oportunitats"
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Informe d'oportunitats"
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Informe d'oportunitats"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr "Dia"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Any"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Perdudes"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Guanyades"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Import guanyades"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Convertides"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Import convertides"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Convertides"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Import convertides"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Iniciativa/Oportunitat"
diff --git a/modules/sale_opportunity/locale/cs.po b/modules/sale_opportunity/locale/cs.po
new file mode 100644
index 0000000000..6363a5f658
--- /dev/null
+++ b/modules/sale_opportunity/locale/cs.po
@@ -0,0 +1,562 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/de.po b/modules/sale_opportunity/locale/de.po
new file mode 100644
index 0000000000..05113d3576
--- /dev/null
+++ b/modules/sale_opportunity/locale/de.po
@@ -0,0 +1,520 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Von Datum"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr "Zeitraum"
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Bis Datum"
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Umgewandelte Verkaufschancen"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Umgewandelte Verkaufschancen pro Mitarbeiter"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Umgewandelte Verkaufschancen pro Mitarbeiter"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Umgewandelte Verkaufschancen"
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Verkaufschancen"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Verkaufschancen"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Trend Betrag"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Umwandlungsrate"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Trend Umwandlungsrate"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Umgewandelter Betrag"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Trend Umgewandelter Betrag"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Anzahl Verkaufschancen"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Trend Anzahl"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Gewinnquote"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Trend Gewinnquote"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Trend Gewonnener Betrag"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Interessenten und Verkaufschancen"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Verkaufschancen"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Verkaufschancen Berichtskontext"
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Auswertung Umgewandelte Verkaufschancen"
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Auswertung Umgewandelte Verkaufschancen pro Mitarbeiter"
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Auswertung Umgewandelte Verkaufschancen pro Mitarbeiter"
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Auswertung Umgewandelte Verkaufschancen"
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Auswertung Verkaufschancen"
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Auswertung Verkaufschancen"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr "Tag"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Monat"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Jahr"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Gewonnener Betrag"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Umgewandelter Betrag"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Umgewandelt"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Umgewandelter Betrag"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Anzahl"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Interessent/Chance"
diff --git a/modules/sale_opportunity/locale/es.po b/modules/sale_opportunity/locale/es.po
new file mode 100644
index 0000000000..6ac1a2e664
--- /dev/null
+++ b/modules/sale_opportunity/locale/es.po
@@ -0,0 +1,516 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Desde la fecha"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr "Periodo"
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Hasta la fecha"
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Conversión de oportunidades"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Conversión de oportunidades por empleado"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Conversión de oportunidades por empleado"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Conversión de oportunidades"
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Oportunidades"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Oportunidades"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Tendencia importe"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Ratio de conversión"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Tendencia conversión"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Importe convertidas"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Tendencia importe convertidas"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Número de oportunidades"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Tendencia número"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Ratio ganadas"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Tendencia ganadas"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Tendencia importe ganadas"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Iniciativas y oportunidades"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Oportunidades"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Contexto informes oportunidades"
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Informe de conversiones de oportunidades"
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Informe de conversiones de oportunidades por empleado"
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Informe de conversiones de oportunidades por empleado"
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Informe de conversiones de oportunidades"
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Informes de oportunidades"
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Informes de oportunidades"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr "Día"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Mes"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Año"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Perdidas"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Ganadas"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Importe ganadas"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Importe convertidas"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Convertidas"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Importe convertidas"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Iniciativa/Oportunidad"
diff --git a/modules/sale_opportunity/locale/es_419.po b/modules/sale_opportunity/locale/es_419.po
new file mode 100644
index 0000000000..979a9cfd5a
--- /dev/null
+++ b/modules/sale_opportunity/locale/es_419.po
@@ -0,0 +1,556 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Oportunidades de venta por mes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Oportunidad de venta por empleado"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Oportunidad de venta por empleado"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Oportunidades de venta por mes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Línea de oportunidad de venta"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Línea de oportunidad de venta"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Convertir a venta"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Creado por usuario"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Creado por usuario"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Perdida"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Línea de oportunidad de venta"
+
+#, 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"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Contexto de oportunidades de venta por empleado"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Oportunidades de venta por mes"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Oportunidad de venta por empleado"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Oportunidad de venta por empleado"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Oportunidades de venta por mes"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Línea de oportunidad de venta"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Línea de oportunidad de venta"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Ganada"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Creado por usuario"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Creado por usuario"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Creado por usuario"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Creado por usuario"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/et.po b/modules/sale_opportunity/locale/et.po
new file mode 100644
index 0000000000..5565ee3dd8
--- /dev/null
+++ b/modules/sale_opportunity/locale/et.po
@@ -0,0 +1,578 @@
+#
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Ettevõte"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Alguskuupäev"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Lõppkuupäev"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Töötaja"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Töötaja"
+
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Võimalused"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Võimlaused töötaja lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Võimlaused töötaja lõikes"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Võimalused"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Võimalused"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Võimalused"
+
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Väärtus"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Väärtus"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Pöördumise tõenäosus"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Muudetud"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Muudetud"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Muudetud"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Kaotatud"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Võimalused"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Number"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Võidetud"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Võidetud väärtus"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Kasutaja ettevõttes"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Potentsiaalid ja võimalused"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Võimalused"
+
+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"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Müügi võimalus töötaja lõikes - sisu"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Müügi võimalus kuu lõikes"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Müügi võimalus töötaja lõikes"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Müügi võimalus töötaja lõikes"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Müügi võimalus kuu lõikes"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Müügi võimaluse rida"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Müügi võimaluse rida"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Kuu"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Aasta"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Võidetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Võidetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Kaotatud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Võidetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Võidetud väärtus"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Väärtus"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Muudetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Muudetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Number"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Väärtus"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Muudetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Muudetud"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Number"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Potesntsiaal/Võimalus"
diff --git a/modules/sale_opportunity/locale/fa.po b/modules/sale_opportunity/locale/fa.po
new file mode 100644
index 0000000000..e9ea7b3a72
--- /dev/null
+++ b/modules/sale_opportunity/locale/fa.po
@@ -0,0 +1,574 @@
+#
+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,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 "واحد"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "شرکت"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "تاریخ شروع"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "تاریخ پایان"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "کارمند"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_form"
+msgid "Leads and Opportunities"
+msgstr "فرصت ها و راهبردها"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "فرصت ها/راهبردهای فروش"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "فرصت ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "فرصت ها در هر کارمند"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "فرصت ها در هر کارمند"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "فرصت ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "فرصت ها"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+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\" شما باید ابتدا آنرا لغو کنید."
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "مقدار"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "مقدار"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "نرخ تبدیل"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "نرخ تبدیل"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "مقدار تبدیل شده"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "مقدار تبدیل شده"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "گم شده"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "فرصت ها"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "نرخ برد"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "نرخ برد"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "برد"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "فرصت ها و راهبردها"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+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 "سطر فرصت فروش"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "مفاد فرصت فروش در هر کارمند"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "فرصت های فروش در هر ماه"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "فرصت فروش در هر کارمند"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "فرصت فروش در هر کارمند"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "فرصت های فروش در هر ماه"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "سطر فرصت فروش"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "ماه"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "سال"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "گم شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "برد"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "گم شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "برد"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "گم شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "برد"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "مقدار برد"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "مقدار"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "مقدار تبدیل شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "شماره"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "مقدار"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "تبدیل شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "مقدار تبدیل شده"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "شماره"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "هدایت / فرصت"
diff --git a/modules/sale_opportunity/locale/fi.po b/modules/sale_opportunity/locale/fi.po
new file mode 100644
index 0000000000..892acfc1c5
--- /dev/null
+++ b/modules/sale_opportunity/locale/fi.po
@@ -0,0 +1,561 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/fr.po b/modules/sale_opportunity/locale/fr.po
new file mode 100644
index 0000000000..292b12ece8
--- /dev/null
+++ b/modules/sale_opportunity/locale/fr.po
@@ -0,0 +1,519 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Date de début"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr "Période"
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Date de fin"
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Conversions d'opportunité"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Conversions d'opportunités par employé"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Conversions d'opportunités par employé"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Conversions d'opportunité"
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunités"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunités"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Tendance du montant"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Taux de conversion"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Tendance de conversion"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Convertis"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Montant converti"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Tendance du montant converti"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Perdues"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Nombre d'opportunités"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Tendance du nombre"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Taux de réussite"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Tendance de réussite"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Gagnées"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Tendance du montant gagné"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Prospects et opportunités"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunités"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Contexte de rapport sur les opportunités de vente"
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Rapport de conversion d'opportunités de ventes"
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Rapport de conversion d'opportunités de ventes par employé"
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Rapport de conversion d'opportunités de ventes par employé"
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Rapport de conversion d'opportunités de ventes"
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Rapports d'opportunités de ventes"
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Rapports d'opportunités de ventes"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr "Jour"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Mois"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Année"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Perdues"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Gagnées"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Perdues"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Gagnées"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Perdues"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Gagnées"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Montant gagné"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converties"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Montant converti"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converties"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Montant converti"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Nombre"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Contact / Opportunité"
diff --git a/modules/sale_opportunity/locale/hu.po b/modules/sale_opportunity/locale/hu.po
new file mode 100644
index 0000000000..52e31a6916
--- /dev/null
+++ b/modules/sale_opportunity/locale/hu.po
@@ -0,0 +1,585 @@
+#
+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"
+
+#, 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.reporting.context,company:"
+msgid "Company"
+msgstr "Társaság"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "utolsó módosítás dátuma"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Alkalmazott"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Alkalmazott"
+
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Szám"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "von"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Hónap"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Év"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "von"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "von"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "von"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Szám"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/id.po b/modules/sale_opportunity/locale/id.po
new file mode 100644
index 0000000000..7305825dd0
--- /dev/null
+++ b/modules/sale_opportunity/locale/id.po
@@ -0,0 +1,550 @@
+#
+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,description:"
+msgid "Description"
+msgstr "Deskripsi"
+
+msgctxt "field:sale.opportunity,employee:"
+msgid "Employee"
+msgstr "Karyawan"
+
+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 ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Tanggal Awal"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Tanggal Akhir"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Karyawan"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Karyawan"
+
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Jumlah"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Jumlah"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Dibuat oleh"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Dibuat oleh"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Nomor"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Jumlah"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+#, fuzzy
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr ""
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Bulan"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Tahun"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Jumlah"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Jumlah"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Jumlah"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Jumlah"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Dibuat oleh"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Dibuat oleh"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Nomor"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Jumlah"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Dibuat oleh"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Dibuat oleh"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/it.po b/modules/sale_opportunity/locale/it.po
new file mode 100644
index 0000000000..d89e78fe9c
--- /dev/null
+++ b/modules/sale_opportunity/locale/it.po
@@ -0,0 +1,588 @@
+#
+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,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à"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Azienda"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Data iniziale"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Data finale"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Dipendente"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Dipendente"
+
+#, 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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+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 "Annullato"
+
+#, 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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Importo"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Importo"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "tasso di conversione"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "tasso di conversione"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "convertito"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "importo convertito"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "importo convertito"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Perso"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Numero"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "tasso di aggiudicazione"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "tasso di aggiudicazione"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "conseguito"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "importo conseguito"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "context opportunity di vendita per dipendente"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "opportunity di vendita per mese"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "opportunity di vendita per dipendente"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "opportunity di vendita per dipendente"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "opportunity di vendita per mese"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "riga opportunity di vendita"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "riga opportunity di vendita"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Mese"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Anno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Perso"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "conseguito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Perso"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "conseguito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Perso"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "conseguito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "importo conseguito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Importo"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "convertito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "importo convertito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Numero"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Importo"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "convertito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "importo convertito"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Numero"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "lead / opportunity"
diff --git a/modules/sale_opportunity/locale/lo.po b/modules/sale_opportunity/locale/lo.po
new file mode 100644
index 0000000000..4958c1c2d2
--- /dev/null
+++ b/modules/sale_opportunity/locale/lo.po
@@ -0,0 +1,599 @@
+#
+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,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.reporting.context,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "ວັນທີເລີ່ມ"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "ວັນທີສິ້ນສຸດ"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "ພະນັກງານ"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "ເລກທີ"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "ມູນຄ່າ"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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 "ວອນ ເກົາຫຼີໃຕ້"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "ເດືອນ"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "ປີ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "ວອນ ເກົາຫຼີໃຕ້"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "ມູນຄ່າ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "ເລກທີ"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/lt.po b/modules/sale_opportunity/locale/lt.po
new file mode 100644
index 0000000000..fce47fa797
--- /dev/null
+++ b/modules/sale_opportunity/locale/lt.po
@@ -0,0 +1,565 @@
+#
+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,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 ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Organizacija"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Pradžios data"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Pabaigos data"
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Vonas"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/nl.po b/modules/sale_opportunity/locale/nl.po
new file mode 100644
index 0000000000..b2d12cc9f6
--- /dev/null
+++ b/modules/sale_opportunity/locale/nl.po
@@ -0,0 +1,518 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Verkoopkans reeks"
+
+msgctxt "field:sale.configuration.sequence,sale_opportunity_sequence:"
+msgid "Opportunity Sequence"
+msgstr "Verkoopkans reeks"
+
+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 "Succes kans"
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr "Omgezet door"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+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 "Verkoopkans"
+
+msgctxt "field:sale.opportunity.line,opportunity_state:"
+msgid "Opportunity State"
+msgstr "Status verkoopkans"
+
+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.reporting.context,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Vanaf datum"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr "Periode"
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Tot datum"
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+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_form"
+msgid "Leads and Opportunities"
+msgstr "Verkoopkansen"
+
+msgctxt "model:ir.action,name:act_opportunity_form2"
+msgid "Sales Leads/Opportunities"
+msgstr "Verkoopkansen"
+
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Verkoopkansen"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Verkoopkansen per werknemer"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Verkoopkansen per werknemer"
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Verkoopkansen"
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Verkoopkansen"
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Verkoopkansen"
+
+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 "Omgezet"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_opportunity_form_domain_leads"
+msgid "Leads"
+msgstr "Potenties"
+
+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 "Verkoopkansen"
+
+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 verkoopkans \"%(opportunity)s\" te verwijderen, moet u deze annuleren."
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Ontwikkeling van het bedrag"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Conversie percentage"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Conversie trend"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Geconverteerd"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Geconverteerd bedrag"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Ontwikkeling geconverteerd bedrag"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Aantal verkoopkansen"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Ontwikkeling van het aantal"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Percentage gewonnen"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Ontwikkeling gewonnen"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Ontwikkeling van gewonnen bedrag"
+
+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 "Omzetten naar verkoop"
+
+msgctxt "model:ir.model.button,string:opportunity_lead_button"
+msgid "Set as Lead"
+msgstr "Markeer als potentie"
+
+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 "Omzetten naar verkoopkans"
+
+msgctxt "model:ir.rule.group,name:rule_group_opportunity_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_conversion_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.sequence,name:sequence_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Verkoopkans"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale_opportunity"
+msgid "Sale Opportunity"
+msgstr "Verkoopkans"
+
+msgctxt "model:ir.ui.menu,name:menu_opportunity_form"
+msgid "Leads and Opportunities"
+msgstr "Verkoopkansen"
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Verkoopkansen"
+
+msgctxt "model:res.group,name:group_opportunity"
+msgid "Sale Opportunity"
+msgstr "Verkoopkans"
+
+msgctxt "model:sale.opportunity,name:"
+msgid "Sale Opportunity"
+msgstr "Verkoopkans"
+
+msgctxt "model:sale.opportunity.line,name:"
+msgid "Sale Opportunity Line"
+msgstr "Verkoopkans regel"
+
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Context rapportering verkoopkansen"
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Rapportering conversie verkoopkansen"
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Rapportage verkoopkansen conversie per werknemer"
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Rapportage verkoopkansen conversie per werknemer"
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Rapportering conversie verkoopkansen"
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Rapportage verkoopkansen"
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Rapportage verkoopkansen"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Converted"
+msgstr "Omgezet"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lead"
+msgstr "Potentie"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Opportunity"
+msgstr "Verkoopkans"
+
+msgctxt "selection:sale.opportunity,state:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr "Dag"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Maand"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Jaar"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Verloren"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Gewonnen"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Gewonnen bedrag"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Geconverteerd"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Geconverteerd bedrag"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Geconverteerd"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Geconverteerd bedrag"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Verkoopkans"
diff --git a/modules/sale_opportunity/locale/pl.po b/modules/sale_opportunity/locale/pl.po
new file mode 100644
index 0000000000..549e8f1cce
--- /dev/null
+++ b/modules/sale_opportunity/locale/pl.po
@@ -0,0 +1,579 @@
+#
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Firma"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Data rozpoczęcia"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Data ukończenia"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Pracownik"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Pracownik"
+
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Numer"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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"
+
+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_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Miesiąc"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Rok"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Numer"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Numer"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/pt.po b/modules/sale_opportunity/locale/pt.po
new file mode 100644
index 0000000000..bcf3f15976
--- /dev/null
+++ b/modules/sale_opportunity/locale/pt.po
@@ -0,0 +1,587 @@
+#
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Empresa"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Data de início"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Data de extremidade"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Empregado"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Empregado"
+
+#, 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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Taxa de Conversão"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Taxa de Conversão"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Convertido"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Montante Convertido"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Montante Convertido"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Número"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Taxa de Ganho"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Taxa de Ganho"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Ganhou"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Montante Ganho"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Contexto da Oportunidade de Venda por Empregado"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Oportunidade de Venda por Mês"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Oportunidade de Venda por Empregado"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Oportunidade de Venda por Empregado"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Oportunidade de Venda por Mês"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Linha da Oportunidade de Venda"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Linha da Oportunidade de Venda"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Mês"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Ano"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Ganhou"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Ganhou"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Perdida"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Ganhou"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Montante Ganho"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Convertido"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Montante Convertido"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Número"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Quantidade"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Convertido"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Montante Convertido"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Lead/Oportunidade"
diff --git a/modules/sale_opportunity/locale/ro.po b/modules/sale_opportunity/locale/ro.po
new file mode 100644
index 0000000000..c7a1d96d84
--- /dev/null
+++ b/modules/sale_opportunity/locale/ro.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 ""
+
+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,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 ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Companie"
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Angajat"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Angajat"
+
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Suma"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Suma"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Număr"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Suma"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr ""
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Lună"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Suma"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Suma"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Pierdut"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Suma"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Suma"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Număr"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/ru.po b/modules/sale_opportunity/locale/ru.po
new file mode 100644
index 0000000000..9df3df8028
--- /dev/null
+++ b/modules/sale_opportunity/locale/ru.po
@@ -0,0 +1,589 @@
+#
+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,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 "Единица измерения"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Организация"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Дата начала"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Дата окончания"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Сотрудник"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Частота обращения"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Частота обращения"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Обращенные"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Кол-во обращенных"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Кол-во обращенных"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Утраченная"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Номер"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Вона"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Сумма"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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 "Строка продажи Возможных"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Продажа Возможной по сотрудникам по месяцам"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Продажа Возможной по месяцам"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Продажа Возможной по сотрудникам"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Продажа Возможной по сотрудникам"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Продажа Возможной по месяцам"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Строка продажи Возможных"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+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 "Вона"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Месяц"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Год"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Утраченная"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Вона"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Утраченная"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Вона"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Утраченная"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Вона"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Обращенные"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Кол-во обращенных"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Сумма"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Обращенные"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Кол-во обращенных"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Номер"
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Неопределенная/Возможная"
diff --git a/modules/sale_opportunity/locale/sl.po b/modules/sale_opportunity/locale/sl.po
new file mode 100644
index 0000000000..f644da8d94
--- /dev/null
+++ b/modules/sale_opportunity/locale/sl.po
@@ -0,0 +1,588 @@
+#
+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,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"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,company:"
+msgid "Company"
+msgstr "Družba"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "Začetni datum"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr "Končni datum"
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr "Zaposlenec"
+
+#, fuzzy
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+msgstr "Zaposlenec"
+
+#, 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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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 ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr "Znesek"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr "Znesek"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Stopnja pretvorbe"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Stopnja pretvorbe"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Pretvorjen znesek"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr "Pretvorjen znesek"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr "Številka"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr "Dobljeni delež"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr "Dobljeni delež"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Dobljeno"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+msgstr "Dobljeni znesek"
+
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Kontekst prodajne priložnosti na zaposlenca"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Mesečna prodajna priložnost"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Prodajna priložnost na zaposlenca"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Prodajna priložnost na zaposlenca"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Mesečna prodajna priložnost"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Postavka prodajne priložnosti"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Postavka prodajne priložnosti"
+
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr "Mesec"
+
+#, fuzzy
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr "Leto"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Dobljeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Dobljeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Zapravljeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Dobljeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr "Dobljeni znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr "Znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Pretvorjen znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr "Številka"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr "Znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Pretvorjeno"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Pretvorjen znesek"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr "Številka"
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr "Sled/Priložnost"
diff --git a/modules/sale_opportunity/locale/tr.po b/modules/sale_opportunity/locale/tr.po
new file mode 100644
index 0000000000..cf05392cdd
--- /dev/null
+++ b/modules/sale_opportunity/locale/tr.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,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.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "Won"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/locale/uk.po b/modules/sale_opportunity/locale/uk.po
new file mode 100644
index 0000000000..e25e4d4f4c
--- /dev/null
+++ b/modules/sale_opportunity/locale/uk.po
@@ -0,0 +1,516 @@
+#
+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 ""
+
+msgctxt "field:sale.opportunity,converted_by:"
+msgid "Converted By"
+msgstr ""
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+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.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr ""
+
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr ""
+
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+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 "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr ""
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+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..6af1387353
--- /dev/null
+++ b/modules/sale_opportunity/locale/zh_CN.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 "Converted"
+
+msgctxt "field:sale.opportunity,currency:"
+msgid "Currency"
+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.reporting.context,company:"
+msgid "Company"
+msgstr ""
+
+#, fuzzy
+msgctxt "field:sale.opportunity.reporting.context,from_date:"
+msgid "From Date"
+msgstr "写入日期"
+
+msgctxt "field:sale.opportunity.reporting.context,period:"
+msgid "Period"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.context,to_date:"
+msgid "To Date"
+msgstr ""
+
+msgctxt "field:sale.opportunity.reporting.conversion.employee,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt ""
+"field:sale.opportunity.reporting.conversion.employee.time_series,employee:"
+msgid "Employee"
+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_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"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_employee_time_series"
+msgid "Opportunity Conversions per Employee"
+msgstr "Opportunities per Employee"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_conversion_time_series"
+msgid "Opportunity Conversions"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.action,name:act_reporting_main_time_series"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+#, 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.message,text:msg_sale_opportunity_reporting_amount"
+msgid "Amount"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_amount_trend"
+msgid "Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_conversion_rate"
+msgid "Conversion Rate"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_conversion_trend"
+msgid "Conversion Trend"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_converted"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_converted_amount_trend"
+msgid "Converted Amount Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_lost"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_help"
+msgid "Number of opportunities"
+msgstr "Opportunities"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_number_trend"
+msgid "Number Trend"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_rate"
+msgid "Winning Rate"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_winning_trend"
+msgid "Winning Trend"
+msgstr ""
+
+#, fuzzy
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "model:ir.message,text:msg_sale_opportunity_reporting_won_amount"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt ""
+"model:ir.message,text:msg_sale_opportunity_reporting_won_amount_trend"
+msgid "Won Amount Trend"
+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_reporting_conversion_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_employee_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_conversion_time_series_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_reporting_main_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt ""
+"model:ir.rule.group,name:rule_group_reporting_main_time_series_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_form"
+msgid "Leads and Opportunities"
+msgstr "Leads and Opportunities"
+
+#, fuzzy
+msgctxt "model:ir.ui.menu,name:menu_reporting_opportunity"
+msgid "Opportunities"
+msgstr "Opportunities"
+
+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.reporting.context,name:"
+msgid "Sale Opportunity Reporting Context"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.employee,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt ""
+"model:sale.opportunity.reporting.conversion.employee.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion per Employee"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.conversion.time_series,name:"
+msgid "Sale Opportunity Reporting Conversion"
+msgstr "Opportunities per Employee per Month"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, fuzzy
+msgctxt "model:sale.opportunity.reporting.main.time_series,name:"
+msgid "Sale Opportunity Reporting"
+msgstr "Sale Opportunity"
+
+#, 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 "圆"
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Day"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Month"
+msgstr ""
+
+msgctxt "selection:sale.opportunity.reporting.context,period:"
+msgid "Year"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "view:sale.opportunity.reporting.conversion.employee.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "view:sale.opportunity.reporting.conversion.time_series:"
+msgid "Won Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "%"
+msgstr "%"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Lost"
+msgstr "Lost"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won"
+msgstr "圆"
+
+msgctxt "view:sale.opportunity.reporting.conversion:"
+msgid "Won Amount"
+msgstr ""
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main.time_series:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Amount"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted"
+msgstr "Converted"
+
+#, fuzzy
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Converted Amount"
+msgstr "Converted"
+
+msgctxt "view:sale.opportunity.reporting.main:"
+msgid "Number"
+msgstr ""
+
+#, fuzzy
+msgctxt "view:sale.opportunity:"
+msgid "%"
+msgstr "%"
+
+msgctxt "view:sale.opportunity:"
+msgid "Lead/Opportunity"
+msgstr ""
diff --git a/modules/sale_opportunity/message.xml b/modules/sale_opportunity/message.xml
new file mode 100644
index 0000000000..86993604f5
--- /dev/null
+++ b/modules/sale_opportunity/message.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+ To delete opportunity "%(opportunity)s", you must cancel it.
+
+
+ You cannot modify the opportunity origin of the sale "%(sale)s".
+
+
+ Number of opportunities
+
+
+ Number Trend
+
+
+ Amount
+
+
+ Amount Trend
+
+
+ Converted
+
+
+ Conversion Rate
+
+
+ Conversion Trend
+
+
+ Converted Amount
+
+
+ Converted Amount Trend
+
+
+ Won
+
+
+ Winning Rate
+
+
+ Winning Trend
+
+
+ Won Amount
+
+
+ Won Amount Trend
+
+
+ Lost
+
+
+
diff --git a/modules/sale_opportunity/opportunity.py b/modules/sale_opportunity/opportunity.py
new file mode 100644
index 0000000000..7d35e132ab
--- /dev/null
+++ b/modules/sale_opportunity/opportunity.py
@@ -0,0 +1,615 @@
+# 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 itertools import groupby
+
+from sql import Null
+from sql.functions import CharLength
+
+from trytond.i18n import gettext
+from trytond.ir.attachment import AttachmentCopyMixin
+from trytond.ir.note import NoteCopyMixin
+from trytond.model import (
+ Index, ModelSQL, ModelView, Workflow, fields, sequence_ordered)
+from trytond.model.exceptions import AccessError
+from trytond.modules.company.model import employee_field, set_employee
+from trytond.modules.currency.fields import Monetary
+from trytond.pool import Pool
+from trytond.pyson import Bool, Eval, Get, If, In
+from trytond.transaction import Transaction
+
+
+class SaleOpportunity(
+ Workflow, ModelSQL, ModelView,
+ AttachmentCopyMixin, NoteCopyMixin):
+ 'Sale Opportunity'
+ __name__ = "sale.opportunity"
+ _history = True
+ _rec_name = 'number'
+
+ _states_start = {
+ 'readonly': Eval('state') != 'lead',
+ }
+ _states_stop = {
+ 'readonly': Eval('state').in_(
+ ['converted', 'won', 'lost', 'cancelled']),
+ }
+
+ number = fields.Char("Number", readonly=True, required=True)
+ reference = fields.Char("Reference")
+ party = fields.Many2One(
+ 'party.party', "Party",
+ states={
+ 'readonly': Eval('state').in_(['converted', 'lost', 'cancelled']),
+ 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
+ },
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'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", states=_states_stop,
+ domain=[('party', '=', Eval('party'))])
+ company = fields.Many2One(
+ 'company.company', "Company", required=True,
+ states={
+ 'readonly': _states_stop['readonly'] | Eval('party', True),
+ },
+ domain=[
+ ('id', If(In('company', Eval('context', {})), '=', '!='),
+ Get(Eval('context', {}), 'company', 0)),
+ ])
+ currency = fields.Many2One(
+ 'currency.currency', "Currency", required=True, states=_states_start)
+ amount = Monetary(
+ "Amount", currency='currency', digits='currency',
+ states=_states_stop,
+ help='Estimated revenue amount.')
+ payment_term = fields.Many2One('account.invoice.payment_term',
+ 'Payment Term', states={
+ 'readonly': In(Eval('state'),
+ ['converted', 'lost', 'cancelled']),
+ })
+ employee = fields.Many2One('company.employee', 'Employee',
+ states={
+ 'readonly': _states_stop['readonly'],
+ 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
+ },
+ domain=[('company', '=', Eval('company'))])
+ start_date = fields.Date("Start Date", required=True, states=_states_start)
+ end_date = fields.Date("End Date", states=_states_stop)
+ description = fields.Char('Description', states=_states_stop)
+ comment = fields.Text('Comment', states=_states_stop)
+ lines = fields.One2Many('sale.opportunity.line', 'opportunity', 'Lines',
+ states=_states_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']),
+ },
+ help="Percentage between 0 and 100.")
+ lost_reason = fields.Text('Reason for loss', states={
+ 'invisible': Eval('state') != 'lost',
+ })
+ 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"),
+ ('lost', "Lost"),
+ ('cancelled', "Cancelled"),
+ ], "State", required=True, sort=False, readonly=True)
+
+ del _states_start
+ del _states_stop
+
+ @classmethod
+ def __register__(cls, module_name):
+ pool = Pool()
+ Company = pool.get('company.company')
+ Sale = pool.get('sale.sale')
+ transaction = Transaction()
+ cursor = transaction.connection.cursor()
+ update = transaction.connection.cursor()
+ sql_table = cls.__table__()
+ company = Company.__table__()
+ sale = Sale.__table__()
+
+ table = cls.__table_handler__(module_name)
+ number_exists = table.column_exist('number')
+ currency_exists = table.column_exist('currency')
+
+ # 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')
+
+ # Migration from 6.4: store currency
+ if not currency_exists:
+ value = company.select(
+ company.currency,
+ where=(sql_table.company == company.id))
+ cursor.execute(*sql_table.update(
+ [sql_table.currency],
+ [value]))
+
+ @classmethod
+ def __setup__(cls):
+ cls.number.search_unaccented = False
+ cls.reference.search_unaccented = False
+ super(SaleOpportunity, cls).__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.update({
+ Index(t, (t.reference, Index.Similarity())),
+ Index(t, (t.party, Index.Equality())),
+ Index(
+ t,
+ (t.start_date, Index.Range(order='DESC')),
+ (t.end_date, Index.Range(order='DESC'))),
+ Index(
+ t, (t.state, Index.Equality()),
+ where=t.state.in_(['lead', 'opportunity'])),
+ })
+ 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': {
+ 'pre_validate': [
+ If(~Eval('party'),
+ ('party', '!=', None),
+ ()),
+ If(~Eval('employee'),
+ ('employee', '!=', None),
+ ()),
+ ],
+ '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'],
+ },
+ })
+
+ @classmethod
+ def order_number(cls, tables):
+ table, _ = tables[None]
+ return [CharLength(table.number), table.number]
+
+ @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')
+
+ @fields.depends('amount', 'company')
+ def on_change_company(self):
+ self.payment_term = self.default_payment_term(
+ company=self.company.id if self.company else None)
+ if not self.amount:
+ self.currency = self.default_currency(
+ company=self.company.id if self.company else None)
+
+ @classmethod
+ def default_currency(cls, **pattern):
+ pool = Pool()
+ Company = pool.get('company.company')
+ company = pattern.get('company')
+ if not company:
+ company = cls.default_company()
+ if company:
+ return Company(company).currency.id
+
+ @staticmethod
+ def default_employee():
+ return Transaction().context.get('employee')
+
+ @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 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)
+
+ @fields.depends('party', 'amount', 'company')
+ def on_change_party(self):
+ self.payment_term = self.default_payment_term(
+ company=self.company.id if self.company else None)
+ if self.party:
+ if self.party.customer_payment_term:
+ self.payment_term = self.party.customer_payment_term
+ if not self.amount:
+ if self.party.customer_currency:
+ self.currency = self.party.customer_currency
+
+ 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.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')
+ with Transaction().set_context(company=self.company.id):
+ 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')
+ for company, c_opportunities in groupby(
+ opportunities, key=lambda o: o.company):
+ with Transaction().set_context(company=company.id):
+ today = Date.today()
+ cls.write([o for o in c_opportunities if o.is_forecast], {
+ 'end_date': today,
+ 'state': 'won',
+ })
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('lost')
+ def lost(cls, opportunities):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ for company, c_opportunities in groupby(
+ opportunities, key=lambda o: o.company):
+ with Transaction().set_context(company=company.id):
+ today = Date.today()
+ cls.write([o for o in c_opportunities if o.is_forecast], {
+ 'end_date': today,
+ 'state': 'lost',
+ })
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, opportunities):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ for company, c_opportunities in groupby(
+ opportunities, key=lambda o: o.company):
+ with Transaction().set_context(company=company.id):
+ today = Date.today()
+ cls.write([o for o in c_opportunities if o.is_forecast], {
+ 'end_date': today,
+ 'state': 'cancelled',
+ })
+
+ @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']),
+ }
+
+ opportunity = fields.Many2One(
+ 'sale.opportunity', "Opportunity", ondelete='CASCADE', required=True,
+ states={
+ 'readonly': _states['readonly'] & Bool(Eval('opportunity')),
+ })
+ 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)
+ quantity = fields.Float(
+ "Quantity", digits='unit', required=True, states=_states)
+ unit = fields.Many2One('product.uom', 'Unit', required=True,
+ states=_states)
+
+ del _states
+
+ @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('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
+
+ 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_number_symbol(
+ self.quantity or 0, self.unit, digits=self.unit.digits)
+ + ' %s @ %s' % (self.product.rec_name, self.opportunity.rec_name))
+
+ @classmethod
+ def search_rec_name(cls, name, clause):
+ return [('product.rec_name',) + tuple(clause[1:])]
diff --git a/modules/sale_opportunity/opportunity.xml b/modules/sale_opportunity/opportunity.xml
new file mode 100644
index 0000000000..a0802f1d52
--- /dev/null
+++ b/modules/sale_opportunity/opportunity.xml
@@ -0,0 +1,245 @@
+
+
+
+
+
+ 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
+
+
+
diff --git a/modules/sale_opportunity/opportunity_reporting.py b/modules/sale_opportunity/opportunity_reporting.py
new file mode 100644
index 0000000000..bdbbb5ce63
--- /dev/null
+++ b/modules/sale_opportunity/opportunity_reporting.py
@@ -0,0 +1,465 @@
+# 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 itertools import tee, zip_longest
+
+from dateutil.relativedelta import relativedelta
+from sql import Literal, Null, With
+from sql.aggregate import Count, Min, Sum
+from sql.conditionals import Case
+from sql.functions import CurrentTimestamp
+try:
+ import pygal
+except ImportError:
+ pygal = None
+
+from trytond.i18n import lazy_gettext
+from trytond.model import ModelSQL, ModelView, fields
+from trytond.modules.currency.fields import Monetary
+from trytond.pool import Pool
+from trytond.pyson import Eval, If
+from trytond.transaction import Transaction
+
+
+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_opportunity.msg_sale_opportunity_reporting_number_help'))
+ number_trend = fields.Function(
+ fields.Char(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_number_trend')),
+ 'get_trend')
+
+ amount = Monetary(
+ lazy_gettext('sale_opportunity.msg_sale_opportunity_reporting_amount'),
+ currency='currency', digits='currency')
+ amount_trend = fields.Function(
+ fields.Char(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_amount_trend')),
+ 'get_trend')
+
+ converted = fields.Integer(
+ lazy_gettext(
+ 'sale_opportunity.msg_sale_opportunity_reporting_converted'))
+ conversion_rate = fields.Function(
+ fields.Float(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_conversion_rate'),
+ digits=(1, 4)), 'get_rate')
+ conversion_trend = fields.Function(
+ fields.Char(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_conversion_trend')),
+ 'get_trend')
+ converted_amount = Monetary(
+ lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_converted_amount'),
+ currency='currency', digits='currency')
+ converted_amount_trend = fields.Function(
+ fields.Char(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_converted_amount_trend')),
+ 'get_trend')
+
+ time_series = None
+
+ currency = fields.Function(
+ fields.Many2One(
+ 'currency.currency',
+ lazy_gettext('sale.msg_sale_reporting_currency')),
+ 'get_currency')
+
+ @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')
+ Opportunity = pool.get('sale.opportunity')
+ context = Transaction().context
+
+ tables = {}
+ company = context.get('company')
+ tables['opportunity'] = opportunity = Opportunity.__table__()
+ tables['opportunity.company'] = company = Company.__table__()
+ withs = {}
+ currency_opportunity = With(query=Currency.currency_rate_sql())
+ withs['currency_opportunity'] = currency_opportunity
+ currency_company = With(query=Currency.currency_rate_sql())
+ withs['currency_company'] = currency_company
+
+ from_item = (opportunity
+ .join(currency_opportunity,
+ condition=(
+ opportunity.currency == currency_opportunity.currency)
+ & (currency_opportunity.start_date <= opportunity.start_date)
+ & ((currency_opportunity.end_date == Null)
+ | (currency_opportunity.end_date > opportunity.start_date))
+ )
+ .join(company, condition=opportunity.company == company.id)
+ .join(currency_company,
+ condition=(company.currency == currency_company.currency)
+ & (currency_company.start_date <= opportunity.start_date)
+ & ((currency_company.end_date == Null)
+ | (currency_company.end_date > opportunity.start_date))
+ ))
+ return from_item, tables, withs
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ opportunity = tables['opportunity']
+ 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'),
+ opportunity.company.as_('company'),
+ Count(Literal(1)).as_('number'),
+ Sum(opportunity.amount).as_('amount'),
+ Sum(Case(
+ (opportunity.state.in_(cls._converted_states()),
+ Literal(1)), else_=Literal(0))).as_('converted'),
+ Sum(Case(
+ (opportunity.state.in_(cls._converted_states()),
+ opportunity.amount),
+ else_=Literal(0))).as_('converted_amount'),
+ ]
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return Min(opportunity.id)
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return [opportunity.company]
+
+ @classmethod
+ def _where(cls, tables, withs):
+ context = Transaction().context
+ opportunity = tables['opportunity']
+
+ where = opportunity.company == context.get('company')
+
+ date = cls._column_date(tables, withs)
+ from_date = context.get('from_date')
+ if from_date:
+ where &= date >= from_date
+ to_date = context.get('to_date')
+ if to_date:
+ where &= date <= to_date
+ return where
+
+ @classmethod
+ def _column_date(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return opportunity.start_date
+
+ @classmethod
+ def _converted_states(cls):
+ return ['converted', 'won']
+
+ @classmethod
+ def _field_name_strip(cls, name, suffix):
+ name = name[:-len(suffix)]
+ return (name
+ .replace('conversion', 'converted')
+ .replace('winning', 'won'))
+
+ def get_rate(self, name):
+ if self.number:
+ digits = getattr(self.__class__, name).digits[1]
+ name = self._field_name_strip(name, '_rate')
+ value = float(getattr(self, name))
+ return round(value / self.number, digits)
+ else:
+ return 0.0
+
+ @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 = self._field_name_strip(name, '_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
+
+
+class AbstractTimeseries(Abstract):
+
+ date = fields.Date(lazy_gettext('sale.msg_sale_reporting_date'))
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order = [('date', 'ASC')]
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ return super()._columns(tables, withs) + [
+ cls._column_date(tables, withs).as_('date')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ return super()._group_by(tables, withs) + [
+ cls._column_date(tables, withs)]
+
+
+class AbstractConversion(Abstract):
+
+ won = fields.Integer(
+ lazy_gettext('sale_opportunity.msg_sale_opportunity_reporting_won'))
+ winning_rate = fields.Function(
+ fields.Float(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_winning_rate'),
+ digits=(1, 4)),
+ 'get_rate')
+ winning_trend = fields.Function(
+ fields.Char(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_winning_trend')),
+ 'get_trend')
+ won_amount = Monetary(
+ lazy_gettext(
+ 'sale_opportunity.msg_sale_opportunity_reporting_won_amount'),
+ currency='currency', digits='currency')
+ won_amount_trend = fields.Function(
+ fields.Char(lazy_gettext(
+ 'sale_opportunity.'
+ 'msg_sale_opportunity_reporting_won_amount_trend')),
+ 'get_trend')
+
+ lost = fields.Integer(
+ lazy_gettext('sale_opportunity.msg_sale_opportunity_reporting_lost'))
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return super()._columns(tables, withs) + [
+ Sum(Case(
+ (opportunity.state.in_(cls._won_states()),
+ Literal(1)), else_=Literal(0))).as_('won'),
+ Sum(Case(
+ (opportunity.state.in_(cls._won_states()),
+ opportunity.amount),
+ else_=Literal(0))).as_('won_amount'),
+ Sum(Case(
+ (opportunity.state.in_(cls._lost_states()),
+ Literal(1)), else_=Literal(0))).as_('lost'),
+ ]
+
+ @classmethod
+ def _column_date(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return opportunity.end_date
+
+ @classmethod
+ def _won_states(cls):
+ return ['won']
+
+ @classmethod
+ def _lost_states(cls):
+ return ['lost']
+
+ @classmethod
+ def _opportunity_states(cls):
+ return cls._converted_states() + cls._won_states() + cls._lost_states()
+
+
+class AbstractConversionTimeseries(AbstractConversion, AbstractTimeseries):
+ pass
+
+
+class Context(ModelView):
+ "Sale Opportunity Reporting Context"
+ __name__ = 'sale.opportunity.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')),
+ ()),
+ ])
+ to_date = fields.Date("To Date",
+ domain=[
+ If(Eval('from_date') & Eval('to_date'),
+ ('to_date', '>=', Eval('from_date')),
+ ()),
+ ])
+ period = fields.Selection([
+ ('year', "Year"),
+ ('month', "Month"),
+ ('day', "Day"),
+ ], "Period", required=True)
+
+ @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')
+
+
+class Main(Abstract, ModelView):
+ "Sale Opportunity Reporting"
+ __name__ = 'sale.opportunity.reporting.main'
+
+ time_series = fields.Function(fields.One2Many(
+ 'sale.opportunity.reporting.main.time_series', None,
+ lazy_gettext('sale.msg_sale_reporting_time_series')),
+ 'get_time_series')
+
+ def get_rec_name(self, name):
+ return ''
+
+ def get_time_series(self, name):
+ pool = Pool()
+ Timeseries = pool.get('sale.opportunity.reporting.main.time_series')
+ return [t.id for t in Timeseries.search([])]
+
+
+class MainTimeseries(AbstractTimeseries, ModelView):
+ "Sale Opportunity Reporting"
+ __name__ = 'sale.opportunity.reporting.main.time_series'
+
+
+class Conversion(AbstractConversion, ModelView):
+ "Sale Opportunity Reporting Conversion"
+ __name__ = 'sale.opportunity.reporting.conversion'
+
+ time_series = fields.Function(fields.One2Many(
+ 'sale.opportunity.reporting.conversion.time_series', None,
+ lazy_gettext('sale.msg_sale_reporting_time_series')),
+ 'get_time_series')
+
+ def get_rec_name(self, name):
+ return ''
+
+ def get_time_series(self, name):
+ pool = Pool()
+ Timeseries = pool.get(
+ 'sale.opportunity.reporting.conversion.time_series')
+ return [t.id for t in Timeseries.search([])]
+
+
+class ConversionTimeseries(AbstractConversionTimeseries, ModelView):
+ "Sale Opportunity Reporting Conversion"
+ __name__ = 'sale.opportunity.reporting.conversion.time_series'
+
+
+class EmployeeMixin:
+ __slots__ = ()
+
+ employee = fields.Many2One('company.employee', "Employee")
+
+ @classmethod
+ def _columns(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return super()._columns(tables, withs) + [
+ opportunity.employee.as_('employee')]
+
+ @classmethod
+ def _group_by(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return super()._group_by(tables, withs) + [
+ opportunity.employee]
+
+ def get_rec_name(self, name):
+ return self.employee.rec_name
+
+
+class ConversionEmployee(EmployeeMixin, AbstractConversion, ModelView):
+ "Sale Opportunity Reporting Conversion per Employee"
+ __name__ = 'sale.opportunity.reporting.conversion.employee'
+
+ time_series = fields.One2Many(
+ 'sale.opportunity.reporting.conversion.employee.time_series',
+ 'employee', lazy_gettext('sale.msg_sale_reporting_time_series'))
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls._order.insert(0, ('employee', 'ASC'))
+
+ @classmethod
+ def _column_id(cls, tables, withs):
+ opportunity = tables['opportunity']
+ return opportunity.employee
+
+ @classmethod
+ def _where(cls, tables, withs):
+ opportunity = tables['opportunity']
+ where = super()._where(tables, withs)
+ where &= opportunity.employee != Null
+ return where
+
+
+class ConversionEmployeeTimeseries(
+ EmployeeMixin, AbstractConversionTimeseries, ModelView):
+ "Sale Opportunity Reporting Conversion per Employee"
+ __name__ = 'sale.opportunity.reporting.conversion.employee.time_series'
diff --git a/modules/sale_opportunity/opportunity_reporting.xml b/modules/sale_opportunity/opportunity_reporting.xml
new file mode 100644
index 0000000000..c480427d7e
--- /dev/null
+++ b/modules/sale_opportunity/opportunity_reporting.xml
@@ -0,0 +1,462 @@
+
+
+
+
+
+
+
+ sale.opportunity.reporting.context
+ form
+ opportunity_reporting_context_form
+
+
+
+
+
+ sale.opportunity.reporting.main
+ tree
+ opportunity_reporting_main_list
+
+
+
+ sale.opportunity.reporting.main
+ graph
+ opportunity_reporting_main_graph_number
+
+
+
+ sale.opportunity.reporting.main
+ graph
+ opportunity_reporting_main_graph_amount
+
+
+
+ Opportunities
+ sale.opportunity.reporting.main
+ sale.opportunity.reporting.context
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.opportunity.reporting.main.time_series
+ tree
+ opportunity_reporting_main_time_series_list
+
+
+
+ sale.opportunity.reporting.main.time_series
+
+
+ opportunity_reporting_main_time_series_graph_number
+
+
+
+ sale.opportunity.reporting.main.time_series
+
+
+ opportunity_reporting_main_time_series_graph_amount
+
+
+
+ Opportunities
+ sale.opportunity.reporting.main.time_series
+ sale.opportunity.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.opportunity.reporting.main,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.opportunity.reporting.conversion
+ tree
+ opportunity_reporting_conversion_list
+
+
+
+ sale.opportunity.reporting.conversion
+ graph
+ opportunity_reporting_conversion_graph_number
+
+
+
+ sale.opportunity.reporting.conversion
+ graph
+ opportunity_reporting_conversion_graph_amount
+
+
+
+ Opportunity Conversions
+ sale.opportunity.reporting.conversion
+ sale.opportunity.reporting.context
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.opportunity.reporting.conversion.time_series
+ tree
+ opportunity_reporting_conversion_time_series_list
+
+
+
+ sale.opportunity.reporting.conversion.time_series
+
+
+ opportunity_reporting_conversion_time_series_graph_number
+
+
+
+ sale.opportunity.reporting.conversion.time_series
+
+
+ opportunity_reporting_conversion_time_series_graph_amount
+
+
+
+ Opportunity Conversions
+ sale.opportunity.reporting.conversion.time_series
+ sale.opportunity.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.opportunity.reporting.conversion,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.opportunity.reporting.conversion.employee
+
+
+ opportunity_reporting_conversion_employee_list
+
+
+
+ sale.opportunity.reporting.conversion.employee
+
+
+ opportunity_reporting_conversion_employee_graph_number
+
+
+
+ sale.opportunity.reporting.conversion.employee
+
+
+ opportunity_reporting_conversion_employee_graph_amount
+
+
+
+ Opportunity Conversions per Employee
+ sale.opportunity.reporting.conversion.employee
+ sale.opportunity.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+
+
+
+
+ tree_open
+ sale.opportunity.reporting.conversion,-1
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.opportunity.reporting.conversion.employee.time_series
+ tree
+ opportunity_reporting_conversion_time_series_list
+
+
+
+ sale.opportunity.reporting.conversion.employee.time_series
+ graph
+ opportunity_reporting_conversion_time_series_graph_number
+
+
+
+ sale.opportunity.reporting.conversion.employee.time_series
+ graph
+ opportunity_reporting_conversion_time_series_graph_amount
+
+
+
+ Opportunity Conversions per Employee
+ sale.opportunity.reporting.conversion.employee.time_series
+ sale.opportunity.reporting.context
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_open
+ sale.opportunity.reporting.conversion.employee,-1
+
+
+
+
+ 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..d39cd4c80d
--- /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 Pool, PoolMeta
+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..bd6197a28d
--- /dev/null
+++ b/modules/sale_opportunity/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 find_packages, setup
+
+
+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', '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 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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'sparklines': ['pygal'],
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_opportunity = trytond.modules.sale_opportunity
+ """,
+ )
diff --git a/modules/sale_opportunity/tests/__init__.py b/modules/sale_opportunity/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_opportunity/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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/scenario_sale_opportunity_reporting.rst b/modules/sale_opportunity/tests/scenario_sale_opportunity_reporting.rst
new file mode 100644
index 0000000000..c1fd867ae7
--- /dev/null
+++ b/modules/sale_opportunity/tests/scenario_sale_opportunity_reporting.rst
@@ -0,0 +1,149 @@
+===================================
+Sale Opportunity Reporting 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_chart, get_accounts)
+
+ >>> today = dt.date.today()
+
+Activate modules::
+
+ >>> config = activate_modules('sale_opportunity')
+
+ >>> Employee = Model.get('company.employee')
+ >>> Opportunity = Model.get('sale.opportunity')
+ >>> Party = Model.get('party.party')
+ >>> ProductCategory = Model.get('product.category')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create employees::
+
+ >>> employee1_party = Party(name="Employee 1")
+ >>> employee1_party.save()
+ >>> employee1 = Employee(party=employee1_party)
+ >>> employee1.save()
+
+ >>> employee2_party = Party(name="Employee 2")
+ >>> employee2_party.save()
+ >>> employee2 = Employee(party=employee2_party)
+ >>> employee2.save()
+
+Create parties::
+
+ >>> customer1 = Party(name="Customer 1")
+ >>> customer1.save()
+ >>> customer2 = Party(name="Customer 2")
+ >>> customer2.save()
+
+Create leads and opportunities::
+
+ >>> lead = Opportunity(party=customer1)
+ >>> lead.amount = Decimal('1000.00')
+ >>> lead.save()
+
+ >>> opportunity = Opportunity(party=customer1)
+ >>> opportunity.amount = Decimal('2000.00')
+ >>> opportunity.employee = employee1
+ >>> opportunity.click('opportunity')
+
+ >>> opportunity = Opportunity(party=customer2)
+ >>> opportunity.amount = Decimal('500.00')
+ >>> opportunity.employee = employee2
+ >>> opportunity.end_date = today
+ >>> opportunity.click('opportunity')
+ >>> opportunity.click('convert')
+
+ >>> opportunity = Opportunity(party=customer1)
+ >>> opportunity.amount = Decimal('700.00')
+ >>> opportunity.employee = employee1
+ >>> opportunity.click('opportunity')
+ >>> opportunity.click('convert')
+ >>> sale, = opportunity.sales
+ >>> line = sale.lines.new()
+ >>> line.quantity = 1
+ >>> line.unit_price = Decimal('800.00')
+ >>> sale.invoice_address, = sale.party.addresses
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+
+ >>> opportunity = Opportunity(party=customer2)
+ >>> opportunity.amount = Decimal('200.00')
+ >>> opportunity.employee = employee2
+ >>> opportunity.click('opportunity')
+ >>> opportunity.click('lost')
+
+Check opportunity reporting::
+
+ >>> Main = Model.get('sale.opportunity.reporting.main')
+ >>> context = dict(
+ ... from_date=today,
+ ... to_date=today,
+ ... period='month')
+ >>> with config.set_context(context=context):
+ ... reports = Main.find([])
+ >>> report, = reports
+ >>> report.number
+ 5
+ >>> report.amount == Decimal('4500.00')
+ True
+ >>> report.converted
+ 2
+ >>> report.conversion_rate
+ 0.4
+ >>> report.converted_amount == Decimal('1300.00')
+ True
+
+ >>> report, = report.time_series
+ >>> report.number
+ 5
+ >>> report.amount == Decimal('4500.00')
+ True
+ >>> report.converted
+ 2
+ >>> report.conversion_rate
+ 0.4
+ >>> report.converted_amount == Decimal('1300.00')
+ True
+
+
+Check conversion reporting::
+
+ >>> Conversion = Model.get('sale.opportunity.reporting.conversion')
+ >>> with config.set_context(context=context):
+ ... reports = Conversion.find([])
+ >>> report, = reports
+ >>> report.number
+ 3
+ >>> report.converted
+ 2
+ >>> report.won
+ 1
+ >>> report.winning_rate
+ 0.3333
+ >>> report.won_amount == Decimal('800.00')
+ True
+ >>> report.lost
+ 1
+ >>> len(report.time_series)
+ 1
+
+ >>> ConversionEmployee = Model.get(
+ ... 'sale.opportunity.reporting.conversion.employee')
+ >>> with config.set_context(context=context):
+ ... reports = ConversionEmployee.find([])
+ >>> len(reports)
+ 2
diff --git a/modules/sale_opportunity/tests/test_module.py b/modules/sale_opportunity/tests/test_module.py
new file mode 100644
index 0000000000..b8daff020c
--- /dev/null
+++ b/modules/sale_opportunity/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SaleOpportunityTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test SaleOpportunity module'
+ module = 'sale_opportunity'
+
+
+del ModuleTestCase
diff --git a/modules/sale_opportunity/tests/test_scenario.py b/modules/sale_opportunity/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_opportunity/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_opportunity/tox.ini b/modules/sale_opportunity/tox.ini
new file mode 100644
index 0000000000..2b03bf757d
--- /dev/null
+++ b/modules/sale_opportunity/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_opportunity/* -m unittest discover -s tests
+ coverage report --include=./**/sale_opportunity/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..f5852fabdf
--- /dev/null
+++ b/modules/sale_opportunity/tryton.cfg
@@ -0,0 +1,17 @@
+[tryton]
+version=6.7.0
+depends:
+ account
+ account_invoice
+ company
+ currency
+ party
+ product
+ sale
+ stock
+xml:
+ opportunity.xml
+ party.xml
+ configuration.xml
+ opportunity_reporting.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_form.xml b/modules/sale_opportunity/view/opportunity_form.xml
new file mode 100644
index 0000000000..6ce671fa45
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_form.xml
@@ -0,0 +1,67 @@
+
+
+
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_reporting_context_form.xml b/modules/sale_opportunity/view/opportunity_reporting_context_form.xml
new file mode 100644
index 0000000000..dd66e4962e
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_context_form.xml
@@ -0,0 +1,15 @@
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_graph_amount.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_graph_amount.xml
new file mode 100644
index 0000000000..3cf5f8e1cb
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_graph_amount.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_graph_number.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_graph_number.xml
new file mode 100644
index 0000000000..3cf5f8e1cb
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_graph_number.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_list.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_list.xml
new file mode 100644
index 0000000000..043a7d0401
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_employee_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_graph_amount.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_graph_amount.xml
new file mode 100644
index 0000000000..f2d2358f22
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_graph_amount.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_graph_number.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_graph_number.xml
new file mode 100644
index 0000000000..1ecf9843be
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_graph_number.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_list.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_list.xml
new file mode 100644
index 0000000000..a601c868e5
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_list.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_graph_amount.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_graph_amount.xml
new file mode 100644
index 0000000000..5938277832
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_graph_amount.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_graph_number.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_graph_number.xml
new file mode 100644
index 0000000000..5938277832
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_graph_number.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_list.xml b/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_list.xml
new file mode 100644
index 0000000000..96ce450f82
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_conversion_time_series_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_main_graph_amount.xml b/modules/sale_opportunity/view/opportunity_reporting_main_graph_amount.xml
new file mode 100644
index 0000000000..60c7e0608f
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_main_graph_amount.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_main_graph_number.xml b/modules/sale_opportunity/view/opportunity_reporting_main_graph_number.xml
new file mode 100644
index 0000000000..a93a8c8d27
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_main_graph_number.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_main_list.xml b/modules/sale_opportunity/view/opportunity_reporting_main_list.xml
new file mode 100644
index 0000000000..7fdcf5885f
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_main_list.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_main_time_series_graph_amount.xml b/modules/sale_opportunity/view/opportunity_reporting_main_time_series_graph_amount.xml
new file mode 100644
index 0000000000..5938277832
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_main_time_series_graph_amount.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_main_time_series_graph_number.xml b/modules/sale_opportunity/view/opportunity_reporting_main_time_series_graph_number.xml
new file mode 100644
index 0000000000..5938277832
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_main_time_series_graph_number.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_reporting_main_time_series_list.xml b/modules/sale_opportunity/view/opportunity_reporting_main_time_series_list.xml
new file mode 100644
index 0000000000..2b37dc7e25
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_reporting_main_time_series_list.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_opportunity/view/opportunity_tree.xml b/modules/sale_opportunity/view/opportunity_tree.xml
new file mode 100644
index 0000000000..2e1d0459bb
--- /dev/null
+++ b/modules/sale_opportunity/view/opportunity_tree.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_payment/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_payment/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_payment/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_payment/CHANGELOG b/modules/sale_payment/CHANGELOG
new file mode 100644
index 0000000000..4bb3bee5be
--- /dev/null
+++ b/modules/sale_payment/CHANGELOG
@@ -0,0 +1,38 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_payment/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..f70d30c6a4
--- /dev/null
+++ b/modules/sale_payment/__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 account, 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..228a91889b
--- /dev/null
+++ b/modules/sale_payment/account.py
@@ -0,0 +1,176 @@
+# 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.model import fields
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval, If
+
+
+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 __setup__(cls):
+ super().__setup__()
+ cls.origin.domain['sale.sale'] = [
+ If(~Eval('state').in_(['failed', 'succeeded']),
+ ('state', '!=', 'draft'),
+ ()),
+ If(Eval('state') == 'draft',
+ ('state', '!=', 'cancelled'),
+ ()),
+ ]
+
+ @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 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 = []
+ payments = set(payments)
+ for sale in self.sales:
+ payments.update(sale.payments)
+ payments = list(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')
+
+ super()._post(invoices)
+
+ payments = set()
+ for invoice in invoices:
+ payments.update(invoice.add_payments())
+ if payments:
+ Payment.save(payments)
+ if hasattr(Payment, 'clearing_move'):
+ # Ensure clearing move is created as succeed may happen
+ # before the payment has a line.
+ Payment.set_clearing_move(
+ [p for p in payments if p.state == 'succeeded'])
+ 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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/bg.po
@@ -0,0 +1,19 @@
+#
+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_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..08d2c79de7
--- /dev/null
+++ b/modules/sale_payment/locale/ca.po
@@ -0,0 +1,19 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/cs.po
@@ -0,0 +1,19 @@
+#
+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_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..76c5bfaeea
--- /dev/null
+++ b/modules/sale_payment/locale/de.po
@@ -0,0 +1,23 @@
+#
+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_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..beb69d6e02
--- /dev/null
+++ b/modules/sale_payment/locale/es.po
@@ -0,0 +1,19 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/es_419.po
@@ -0,0 +1,19 @@
+#
+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_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..a0241d8f38
--- /dev/null
+++ b/modules/sale_payment/locale/et.po
@@ -0,0 +1,22 @@
+#
+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_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..fc8fee74a0
--- /dev/null
+++ b/modules/sale_payment/locale/fa.po
@@ -0,0 +1,22 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/fi.po
@@ -0,0 +1,19 @@
+#
+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_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..ae5c7c3e2d
--- /dev/null
+++ b/modules/sale_payment/locale/fr.po
@@ -0,0 +1,22 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/hu.po
@@ -0,0 +1,19 @@
+#
+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_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..994fffa833
--- /dev/null
+++ b/modules/sale_payment/locale/id.po
@@ -0,0 +1,23 @@
+#
+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_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..a44c61f15a
--- /dev/null
+++ b/modules/sale_payment/locale/it.po
@@ -0,0 +1,21 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Pagamenti"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Pagamenti"
+
+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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/lo.po
@@ -0,0 +1,19 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/lt.po
@@ -0,0 +1,19 @@
+#
+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_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..020bc9a868
--- /dev/null
+++ b/modules/sale_payment/locale/nl.po
@@ -0,0 +1,23 @@
+#
+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_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..d5ba593a0f
--- /dev/null
+++ b/modules/sale_payment/locale/pl.po
@@ -0,0 +1,20 @@
+#
+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_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..cc166cd613
--- /dev/null
+++ b/modules/sale_payment/locale/pt.po
@@ -0,0 +1,20 @@
+#
+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_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..521462549f
--- /dev/null
+++ b/modules/sale_payment/locale/ro.po
@@ -0,0 +1,19 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.sale,payments:"
+msgid "Payments"
+msgstr "Plați"
+
+msgctxt "model:ir.action,name:act_payments_relate"
+msgid "Payments"
+msgstr "Plați"
+
+msgctxt "model:ir.message,text:msg_sale_cancel_payment"
+msgid "You cannot cancel sale \"%(sale)s\" because it has payments."
+msgstr "Vânzarea \"%(sale)s\" nu se poate anula pentru că are plați."
+
+msgctxt "model:ir.message,text:msg_sale_draft_payment"
+msgid "You cannot reset to draft sale \"%(sale)s\" because it has payments."
+msgstr "Nu se poate reseta vânzarea \"%(sale)s\" la draft pentru ca are plați."
diff --git a/modules/sale_payment/locale/ru.po b/modules/sale_payment/locale/ru.po
new file mode 100644
index 0000000000..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/ru.po
@@ -0,0 +1,19 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/sl.po
@@ -0,0 +1,19 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/tr.po
@@ -0,0 +1,19 @@
+#
+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_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/uk.po b/modules/sale_payment/locale/uk.po
new file mode 100644
index 0000000000..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/uk.po
@@ -0,0 +1,19 @@
+#
+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_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..d47060c218
--- /dev/null
+++ b/modules/sale_payment/locale/zh_CN.po
@@ -0,0 +1,19 @@
+#
+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_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..a40e70c1c4
--- /dev/null
+++ b/modules/sale_payment/message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ You cannot cancel sale "%(sale)s" because it has payments.
+
+
+ You cannot reset to draft sale "%(sale)s" because it has payments.
+
+
+
diff --git a/modules/sale_payment/sale.py b/modules/sale_payment/sale.py
new file mode 100644
index 0000000000..b7c70c1946
--- /dev/null
+++ b/modules/sale_payment/sale.py
@@ -0,0 +1,89 @@
+# 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 Bool, Eval, If
+
+
+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',
+ })
+
+ @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)
+
+ @property
+ def payment_amount_authorized(self):
+ "Total amount of the authorized payments"
+ return sum(p.amount for p in self.payments if p.is_authorized)
+
+ @property
+ def amount_to_pay(self):
+ "Amount to pay to confirm the sale"
+ return self.total_amount
+
+ @classmethod
+ def payment_confirm(cls, sales):
+ "Confirm the sale based on payment authorization"
+ to_confirm = []
+ for sale in sales:
+ if sale.payment_amount_authorized >= sale.amount_to_pay:
+ to_confirm.append(sale)
+ if to_confirm:
+ to_confirm = cls.browse(to_confirm) # optimize cache
+ cls.confirm(to_confirm)
+
+ @property
+ def credit_limit_amount(self):
+ amount = super().credit_limit_amount
+ return max(0, amount - self.payment_amount_authorized)
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..f2b929fae0
--- /dev/null
+++ b/modules/sale_payment/setup.py
@@ -0,0 +1,152 @@
+#!/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_payment = trytond.modules.sale_payment
+ """,
+ )
diff --git a/modules/sale_payment/tests/__init__.py b/modules/sale_payment/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_payment/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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..9930f88a53
--- /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('submit')
+ >>> payment.state
+ 'submitted'
+
+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):
+ ...
+ DomainValidationError: ...
+
+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):
+ ...
+ DomainValidationError: ...
+
+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('submit')
+ >>> 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/scenario_sale_payment_no_clearing.rst b/modules/sale_payment/tests/scenario_sale_payment_no_clearing.rst
new file mode 100644
index 0000000000..a5e5af30ec
--- /dev/null
+++ b/modules/sale_payment/tests/scenario_sale_payment_no_clearing.rst
@@ -0,0 +1,108 @@
+=================================
+Sale Payment Scenario No Clearing
+=================================
+
+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')
+
+ >>> PaymentJournal = Model.get('account.payment.journal')
+ >>> Party = Model.get('party.party')
+ >>> AccountConfiguration = Model.get('account.configuration')
+ >>> Sale = Model.get('sale.sale')
+ >>> Payment = Model.get('account.payment')
+
+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']
+
+Create payment journal::
+
+ >>> payment_journal = PaymentJournal(
+ ... name="Manual", process_method='manual')
+ >>> payment_journal.save()
+
+Create parties::
+
+ >>> customer = Party(name="Customer")
+ >>> customer.save()
+
+Default account product::
+
+ >>> account_configuration = AccountConfiguration(1)
+ >>> account_configuration.default_category_account_revenue = revenue
+ >>> account_configuration.save()
+
+Create a sale quotation::
+
+ >>> 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'
+
+Pay the sale using payment::
+
+ >>> payment = Payment()
+ >>> payment.journal = payment_journal
+ >>> payment.kind = 'receivable'
+ >>> payment.party = sale.party
+ >>> payment.origin = sale
+ >>> payment.amount = Decimal('100.00')
+ >>> payment.click('submit')
+ >>> payment.state
+ 'submitted'
+ >>> 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
+ 'posted'
diff --git a/modules/sale_payment/tests/test_module.py b/modules/sale_payment/tests/test_module.py
new file mode 100644
index 0000000000..9ac0e11588
--- /dev/null
+++ b/modules/sale_payment/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class AccountPaymentTestCase(ModuleTestCase):
+ 'Test Sale Payment module'
+ module = 'sale_payment'
+
+
+del ModuleTestCase
diff --git a/modules/sale_payment/tests/test_scenario.py b/modules/sale_payment/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_payment/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_payment/tox.ini b/modules/sale_payment/tox.ini
new file mode 100644
index 0000000000..0fd6a4cbde
--- /dev/null
+++ b/modules/sale_payment/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_payment/* -m unittest discover -s tests
+ coverage report --include=./**/sale_payment/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..a617ce80c0
--- /dev/null
+++ b/modules/sale_payment/tryton.cfg
@@ -0,0 +1,14 @@
+[tryton]
+version=6.7.0
+depends:
+ account_invoice
+ account_payment
+ ir
+ res
+ sale
+extras_depend:
+ account_payment_clearing
+ sale_credit_limit
+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_point/.drone.yml b/modules/sale_point/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale_point/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_point/.flake8 b/modules/sale_point/.flake8
new file mode 100644
index 0000000000..bb03d08a82
--- /dev/null
+++ b/modules/sale_point/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,W503
diff --git a/modules/sale_point/.isort.cfg b/modules/sale_point/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_point/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_point/CHANGELOG b/modules/sale_point/CHANGELOG
new file mode 100644
index 0000000000..03a478d9bf
--- /dev/null
+++ b/modules/sale_point/CHANGELOG
@@ -0,0 +1,15 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Add reporting
+* Use negative debit/credit for cash change
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-01
+--------------------------
+* Initial release
diff --git a/modules/sale_point/COPYRIGHT b/modules/sale_point/COPYRIGHT
new file mode 100644
index 0000000000..b97a61c3dd
--- /dev/null
+++ b/modules/sale_point/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_point/LICENSE b/modules/sale_point/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_point/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_point/MANIFEST.in b/modules/sale_point/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_point/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_point/README.rst b/modules/sale_point/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_point/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_point/__init__.py b/modules/sale_point/__init__.py
new file mode 100644
index 0000000000..d078caf0ef
--- /dev/null
+++ b/modules/sale_point/__init__.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.modules.sale.sale_reporting import Abstract
+from trytond.pool import Pool
+
+from . import account, product, sale, sale_reporting, stock
+
+
+def register():
+ Pool.register(
+ sale.POS,
+ sale.POSSale,
+ sale.POSSaleLine,
+ sale.POSCashSession,
+ sale.POSCashSessionRelation,
+ sale.POSPayment,
+ sale.POSPaymentMethod,
+ sale.POSCashTransfer,
+ sale.POSCashTransferType,
+ product.Template,
+ product.Product,
+ product.GrossPrice,
+ stock.Move,
+ account.Move,
+ account.MoveLine,
+ module='sale_point', type_='model')
+ Pool.register(
+ sale.POSPay,
+ module='sale_point', type_='wizard')
+ Pool.register_mixin(sale_reporting.AbstractMixin, Abstract, 'sale_point')
diff --git a/modules/sale_point/account.py b/modules/sale_point/account.py
new file mode 100644
index 0000000000..128bbcda64
--- /dev/null
+++ b/modules/sale_point/account.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 PoolMeta
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'account.move'
+
+ @classmethod
+ def _get_origin(cls):
+ return super()._get_origin() + [
+ 'sale.point.sale', 'sale.point.cash.transfer']
+
+
+class MoveLine(metaclass=PoolMeta):
+ __name__ = 'account.move.line'
+
+ @classmethod
+ def _get_origin(cls):
+ return super()._get_origin() + [
+ 'sale.point.sale.line', 'sale.point.payment']
diff --git a/modules/sale_point/doc/conf.py b/modules/sale_point/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_point/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_point/doc/design.rst b/modules/sale_point/doc/design.rst
new file mode 100644
index 0000000000..6755a61432
--- /dev/null
+++ b/modules/sale_point/doc/design.rst
@@ -0,0 +1,130 @@
+******
+Design
+******
+
+The *Sale Point Module* introduces the concepts that are required to manage
+retail sales.
+
+.. _model-sale.point:
+
+Point of Sale
+=============
+
+The *Point of Sale* concept is used to configure the point where sales happen.
+
+.. seealso::
+
+ The Point of Sale configuration is found by opening the main menu item:
+
+ |Sales --> Configuration --> Points of Sale|__
+
+ .. |Sales --> Configuration --> Points of Sale| replace:: :menuselection:`Sales --> Configuration --> Points of Sale`
+ __ https://demo.tryton.org/model/sale.point
+
+.. _model-sale.point.sale:
+
+Sale
+====
+
+The *Sale* concept registers what quantity of products are sold or returned and
+how the customer paid for them.
+Each sale, at any time, can be in one of several different states.
+A sale progress though these states until it is posted.
+
+Each sale is linked to a `Point ` where it takes place.
+
+A sale is identified by a unique number that is generated automatically from
+the configured *Sequence* for the sale Point.
+It also has other general information like the date and the `Employee
+` who creates the order.
+
+The sale is made up from one, or more, sales lines.
+These lines provide information about which `Products
+` and what quantities are included in the sale.
+
+The total and tax amounts for a sale are derived from the prices and `Taxes
+` of the line's Products.
+
+The amount paid or reimbursed is registered using the `Payment Method
+`.
+Once the amount to paid reaches zero, the sale is done.
+
+On posting the sale it generates the corresponding `Stock Moves
+` for the goods and posts the corresponding `Account
+Move `.
+
+.. seealso::
+
+ Sales are found by opening the main menu item:
+
+ |Sales --> POS Sales|__
+
+ .. |Sales --> POS Sales| replace:: :menuselection:`Sales --> POS Sales`
+ __ https://demo.tryton.org/model/sale.point.sale
+
+Wizards
+-------
+
+.. _wizard-sale.point.sale.pay:
+
+Pay Sale
+^^^^^^^^
+
+The *Pay Sale* wizard allows payments to be registered against the sale.
+If the sale is overpaid the wizard calculates the amount to return.
+Once the sale is fully paid the sale state is automatically set to done.
+
+.. _model-sale.point.cash.session:
+
+Cash Session
+============
+
+The *Cash Session* groups the cash payments and the transfers of a `Point of
+Sale ` over a period.
+The sessions of a point of sale are a chained list that tracks the cash amount
+between each closure.
+
+.. seealso::
+
+ The Cash Sessions are found by opening the main menu item:
+
+ |Sales --> POS Cash Sessions|__
+
+ .. |Sales --> POS Cash Sessions| replace:: :menuselection:`Sales --> POS Cash Sessions`
+ __ https://demo.tryton.org/model/sale.point.cash.session
+.. _model-sale.point.payment.method:
+
+Payment Method
+==============
+
+The *Payment Method* defines the available options for paying a `Sale
+`.
+
+A method can be set to *cash* so it will be used to return change.
+Only one method per company can be set to cash.
+
+.. seealso::
+
+ Payment Methods are found by opening the main menu item:
+
+ |Sales --> Configuration --> POS Payment Methods|__
+
+ .. |Sales --> Configuration --> POS Payment Methods| replace:: :menuselection:`Sales --> Configuration --> POS Payment Methods`
+ __ https://demo.tryton.org/model/sale.point.payment.method
+
+.. _model-sale.point.cash.transfer.type:
+
+Cash Transfer Type
+==================
+
+The *Transfer Type* defines the available options for transferring cash of a
+`Point of Sale `.
+
+.. seealso::
+
+ Cash Transfer Types are found by opening the main menu item:
+
+ |Sales --> Configuration --> POS Cash Transfer Types|__
+
+ .. |Sales --> Configuration --> POS Cash Transfer Types| replace:: :menuselection:`Sales --> Configuration --> POS Cash Transfer Types`
+ __ https://demo.tryton.org/model/sale.point.cash.transfer.type
diff --git a/modules/sale_point/doc/index.rst b/modules/sale_point/doc/index.rst
new file mode 100644
index 0000000000..97420db0f8
--- /dev/null
+++ b/modules/sale_point/doc/index.rst
@@ -0,0 +1,11 @@
+#################
+Sale Point Module
+#################
+
+The *Sale Point Module* allows retail sales to be handled and recorded.
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ releases
diff --git a/modules/sale_point/doc/releases.rst b/modules/sale_point/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_point/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_point/exceptions.py b/modules/sale_point/exceptions.py
new file mode 100644
index 0000000000..c7087547fc
--- /dev/null
+++ b/modules/sale_point/exceptions.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.model.exceptions import ValidationError
+
+
+class SaleValidationError(ValidationError):
+ pass
+
+
+class SessionValidationError(ValidationError):
+ pass
diff --git a/modules/sale_point/locale/bg.po b/modules/sale_point/locale/bg.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/bg.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/ca.po b/modules/sale_point/locale/ca.po
new file mode 100644
index 0000000000..3b5babdc7a
--- /dev/null
+++ b/modules/sale_point/locale/ca.po
@@ -0,0 +1,678 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr "Preu brut"
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr "Plantilla"
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr "Preu brut"
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr "Preus bruts"
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr "Preu brut"
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr "Preus bruts"
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr "Adreça"
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr "A la ubicació"
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr "Diari"
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr "Ubicació de retorn"
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr "Seqüència"
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr "Ubicació d'emmagatzematge"
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr "Impostos inclosos"
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr "Saldo"
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr "Import final"
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr "Propera sessió"
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr "Pagaments"
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr "Sessió anterior"
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr "Import inicial"
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr "Transferències"
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr "Següent"
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr "Anterior"
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr "Moviment"
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr "Sessió"
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr "Tipus"
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr "Diari"
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr "Efectiu"
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr "Mètode"
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr "Estat de la venda"
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr "Sessió"
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr "Efectiu"
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr "Pagat"
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr "A pagar"
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr "Empleat"
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr "Línies"
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr "Moviment"
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr "Pagaments"
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr "Estat"
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr "Total impostos"
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr "Import"
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr "Moviments"
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantitat"
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Estat de la venda"
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr "Unitat"
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr "Preu brut unitari"
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr "Preu unitari de venda"
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Preu unitari"
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr "El preu amb els impostos per defecte inclosos."
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr "El preu amb els impostos per defecte inclosos."
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr "La ubicació on es s'envien els béns quan es venen."
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+"La ubicació on es posen els béns quan es retornen.\n"
+"Si està buit, s'utilitza la ubicació d'emmagatzematge."
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr "La ubicació d'on s'agafen els béns quan es venen."
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr "Marca si el preu unitari inclou impostos."
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Tancament de caixa TPV"
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Tipus de transferència de diners TPV"
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Mètodes de pagament TPV"
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr "Punts de venda"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr "Vendes de TPV"
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr "Pagar venda TPV"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr "Tot"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr "Tancada"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+msgstr "Oberta"
+
+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_done"
+msgid "Done"
+msgstr "Finalitzada"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr "Oberta"
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr "Per eliminar la sessió \"%(session)s\", heu de tornar a obrir-la."
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr "Una sessió només es pot utilitzar com a anterior una vegada."
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+"Per tancar la sessió \"%(session)s\", heu de canviar l'import final per "
+"tenir %(amount)s en lloc de %(end_amount)s."
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+"Per eliminar el pagament \"%(payment)s\", heu de tornar a obrir la venda "
+"\"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Per eliminar el pagament \"%(payment)s\", heu de tornar a obrir la sessió "
+"\"%(session)s\"."
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr "Cada empresa només pot tenir un mètode de pagament en efectiu."
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr "Cada punt de venda només pot tenir una sessió oberta."
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+"No podeu canviar la marca d'impostos inclosos del punt de venda perquè té ja"
+" té vendes."
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+"La venda %(sale)s\" està cancel·lada, de manera que no pot tenir import "
+"pagat."
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+"La venda \"%(sale)s\" està finalitzada, de manera que no pot tenir un import"
+" a pagar."
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr "No podeu eliminar la venda \"%(sale)s\" perquè té un número."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+"No podeu eliminar la transferència \"%(transfer)s\" perquè està "
+"comptabilitzada."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Per eliminar la transferència \"%(transfer)s\" heu de tornar a obrir la "
+"sessió \"%(session)s\"."
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr "Segur que voleu comptabilitzar les sessions?"
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr "Segur que voleu comptabilitzar la transferència?"
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr "Segur que voleu comptabilitzar les vendes?"
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr "Tanca"
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr "Torna a obrir"
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr "Comptabilitza"
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr "Comptabilitzar"
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr "Torna a obrir"
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr "Paga"
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr "Comptabilitzar"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Processa"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr "Usuari a les empreses"
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr "TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Tancament de caixa TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Tipus de transferència de dinero TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Mètodes de pagament TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr "Punts de venda"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr "Vendes TPV"
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr "Preu brut del producte"
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr "TPV"
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr "Comptabilització de TPV"
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr "Punts de venda"
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr "Tacament de caixa TPV"
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr "Relació de sessió de TPV"
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr "Trasnferència de diners TPV"
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr "Tipus de transferència de diners TPV"
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr "Pagament TPV"
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr "Mètode de pagament TPV"
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr "Venda TPV"
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr "Línia de venda TPV"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr "Tancada"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr "Oberta"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr "Comptabilitzada"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr "Esborrany"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr "Comptabilitzada"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr "Cancel·lada"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr "Finalitzada"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr "Oberta"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr "Comptabilitzada"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr "Informació addicional"
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr "Pagaments"
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr "Venda"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr "D'acord"
diff --git a/modules/sale_point/locale/cs.po b/modules/sale_point/locale/cs.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/cs.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/de.po b/modules/sale_point/locale/de.po
new file mode 100644
index 0000000000..816be3d630
--- /dev/null
+++ b/modules/sale_point/locale/de.po
@@ -0,0 +1,682 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr "Bruttopreis"
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr "Artikelvorlage"
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr "Bruttopreis"
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr "Bruttopreise"
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr "Bruttopreis"
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr "Bruttopreise"
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr "Adresse"
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr "Zu Lagerort"
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr "Journal"
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr "Lagerort Rücknahme"
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr "Nummernkreis"
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr "Lagerort Warenabgabe"
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr "Steuer Inklusive"
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr "Saldo"
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr "Endbestand"
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr "Nächste Session"
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr "Zahlungen"
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr "Point of Sale"
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr "Vorherige Session"
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr "Anfangsbestand"
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr "Geldtransits"
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr "Nächste"
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr "Vorherige"
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr "Buchungssatz"
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr "Point of Sale"
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr "Session"
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr "Journal"
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr "Barzahlung"
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr "Methode"
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr "Point of Sale"
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr "Verkaufsstatus"
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr "Session"
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr "Konto"
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr "Barzahlung"
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr "Bezahlt"
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr "Zu Zahlen"
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr "Mitarbeiter"
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr "Positionen"
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr "Buchungssatz"
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr "Zahlungen"
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr "Point of Sale"
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr "Gesamt"
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr "Steuer Gesamt"
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr "Warenbewegungen"
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr "Menge"
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Verkaufsstatus"
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr "Einheit"
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr "Bruttoeinzelpreis"
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr "Listeneinzelpreis"
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Einzelpreis"
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr "Der Preis inklusive der Standardsteuern."
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr "Der Preis inklusive der Standardsteuern."
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr "Der Lagerort in den die Waren beim Verkauf umgelagert werden."
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+"Der Lagerort in den die Waren bei einer Rücknahme eingelagert werden.\n"
+"Leer lassen, um den Lagerort der Warenabgabe zu verwenden."
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr "Der Lagerort aus dem die Waren beim Verkauf entnommen werden."
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr "Aktivieren, wenn der Einzelpreis inklusive Steuern ist."
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Point of Sale Sessions"
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Point of Sale Geldtransitarten"
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Point of Sale Zahlungsarten"
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr "Points of Sale"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr "Point of Sale"
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr "Zahlung Point of Sale Verkauf"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr "Abgeschlossen"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+msgstr "Offen"
+
+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_done"
+msgid "Done"
+msgstr "Erledigt"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr "Offen"
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+"Session \"%(session)s\" muss zuerst geöffnet werden bevor sie gelöscht "
+"werden kann."
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr "Eine Session kann nur einmal als vorherige Session verwendet werden."
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+"Damit die Session \"%(session)s\" abgeschlossen werden kann, muss ein "
+"Endbestand von %(amount)s anstatt %(end_amount)s erreicht werden."
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+"Damit die Zahlung \"%(payment)s\" gelöscht werden kann, muss zuerst der "
+"Verkauf \"%(sale)s\" wieder geöffnet werden."
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Damit die Zahlung \"%(payment)s\" gelöscht werden kann, muss zuerst die "
+"Session \"%(session)s\" wieder geöffnet werden."
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr "Es kann nur eine Barzahlungsart je Unternehmen geben."
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr "Ein Point of Sale kann nur eine offene Session haben."
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+"Die Markierung des Point of Sale für Steuern inklusive kann nicht geändert "
+"werden, weil mit ihm bereits Verkäufe erfasst wurden."
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+"Der Verkauf \"%(sale)s\" wurde annulliert und darf daher keinen gezahlten "
+"Betrag erfasst haben."
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+"Der Verkauf \"%(sale)s\" ist erledigt und darf daher keinen zahlbaren Betrag"
+" haben."
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+"Der Verkauf \"%(sale)s\" kann nicht gelöscht werden, da bereits eine Nummer "
+"vergeben wurde."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+"Der Geldtransfer \"%(transfer)s\" kann nicht gelöscht werden, weil er "
+"festgeschrieben ist."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Damit der Geldtransfer \"%(transfer)s\" gelöscht werden kann, muss erst die "
+"Session \"%(session)s\" wieder geöffnet werden."
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr "Die Session wirklich festschreiben?"
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr "Den Geldtransit wirklich festschreiben?"
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr "Den Verkauf wirklich festschreiben?"
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr "Abschließen"
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr "Wieder öffnen"
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr "Festschreiben"
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr "Festschreiben"
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annullieren"
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr "Wieder öffnen"
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr "Zahlung erfassen"
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr "Festschreiben"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Ausführen"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr "Point of Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Point of Sale Sessions"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Point of Sale Geldtransitarten"
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Point of Sale Zahlungsarten"
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr "Points of Sale"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr "Point of Sale Verkauf"
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr "Artikelbruttopreis"
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr "Point of Sale"
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr "Point of Sale Festschreibung"
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr "Point of Sale"
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr "Point of Sale Session"
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr "Point of Sale Session Beziehung"
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr "Point of Sale Geldtransit"
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr "Point of Sale Geldtransitart"
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr "Point of Sale Zahlung"
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr "Point of Sale Zahlungsart"
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr "Point of Sale Verkauf"
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr "Point of Sale Verkaufsposition"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr "Abgeschlossen"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr "Offen"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr "Festgeschrieben"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr "Entwurf"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr "Festgeschrieben"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr "Annulliert"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr "Erledigt"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr "Offen"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr "Festgeschrieben"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr "Allgemein"
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr "Sonstiges"
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr "Zahlungen"
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr "Verkauf"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr "OK"
diff --git a/modules/sale_point/locale/es.po b/modules/sale_point/locale/es.po
new file mode 100644
index 0000000000..82977e7f51
--- /dev/null
+++ b/modules/sale_point/locale/es.po
@@ -0,0 +1,677 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr "Precio bruto"
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr "Plantilla"
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr "Precio bruto"
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr "Precios brutos"
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr "Precio bruto"
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr "Precios brutos"
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr "Dirección"
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr "A la ubicación"
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr "Diario"
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr "Ubicación de retorno"
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr "Secuencia"
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr "Ubicación de almacenamiento"
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr "Impuestos incluidos"
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr "Saldo"
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr "Importe final"
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr "Próxima sesión"
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr "Pagos"
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr "Punto"
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr "Sesión anterior"
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr "Importe inicial"
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr "Transferencias"
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr "Siguiente"
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr "Anterior"
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr "Movimiento"
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr "Punto"
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr "Sesión"
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr "Tipo"
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr "Cuenta"
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr "Diario"
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr "Efectivo"
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr "Método"
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr "Punto"
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr "Estado de venta"
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr "Sesión"
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr "Cuenta"
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr "Efectivo"
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr "Nombre"
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr "Pagada"
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr "A pagar"
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr "Fecha"
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr "Empleado"
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr "Líneas"
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr "Movimiento"
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr "Número"
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr "Pagos"
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr "Punto"
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr "Estado"
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr "Total impuestos"
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr "Importe"
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr "Empresa"
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr "Moneda"
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr "Movimientos"
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr "Cantidad"
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Estado de la venta"
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr "Unidad"
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr "Precio bruto unitario"
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr "Precio de lista unitario"
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Precio unitario"
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr "El precio con el impuesto por defecto incluido."
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr "El precio con el impuesto por defecto incluido."
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr "La ubicación donde se colocan los bienes cuando se venden."
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+"La ubicación donde se colocan las mercancías cuando se devuelven.\n"
+"Si está vacío, se utiliza la ubicación de almacenamiento."
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr "La ubicación de donde se cogen los bienes cuando se venden."
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr "Compruebe si el precio unitario incluye impuestos."
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Cierre de caja TPV"
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Tipo de transferencia de dinero TPV"
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Métodos de pago TPV"
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr "Puntos de venta"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr "Ventas TPV"
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr "Pagar venta TPV"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr "Todo"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr "Cerrado"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+msgstr "Abierta"
+
+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_done"
+msgid "Done"
+msgstr "Finalizado"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr "Abierto"
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr "Para eliminar la sesión \"%(session)s\" debe volver a abrirla."
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr "Una sesión se puede utilizar como anterior solo una vez."
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+"Para cerrar la sesión \"%(session)s\", debe cambiar el importe final para "
+"tener %(amount)s en lugar de %(end_amount)s."
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+"Para eliminar el pago \"%(payment)s\" debe volver a abrir la venta "
+"\"%(sale)s\"."
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Para eliminar el pago \"%(payment)s\" debe volver a abrir la sesión "
+"\"%(session)s\"."
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr "Cada empresa solo puede tener un método de pago en efectivo."
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr "Cada punto de venta solo puede tener una sesión abierta."
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+"No puede cambiar la marca de impuestos incluidos del punto de venta porque "
+"tiene ventas."
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+"La venta \"%(sale)s\" está cancelada, por lo que no puede tener importe "
+"pagado."
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+"La venta \"%(sale)s\" está realizada, por lo que no se puede tener una "
+"cantidad a pagar."
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr "No puede eliminar la venta \"%(sale)s\" porque tiene un número."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+"No puede eliminar la transferencia \"%(transfer)s\" porque está publicada."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Para eliminar la transferencia \"%(transfer)s\" debe volver a abrir la "
+"sesión \"%(session)s\"."
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr "¿Seguro que quieres contabilizar las sesiones?"
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr "¿Seguro que quieres contabilizar la transferencia?"
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr "¿Seguro que quieres contabilizar las ventas?"
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr "Cerrar"
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr "Volver a abrir"
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr "Contabilizar"
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr "Contabilizar"
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr "Volver a abrir"
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr "Pagar"
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr "Contabilizar"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Procesar"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr "Usuario en las empresas"
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr "TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Cierre de caja TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Tipo de transferencia de dinero TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Métodos de pago TPV"
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr "Puntos de venta"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr "Ventas de TPV"
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr "Precio bruto del producto"
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr "TPV"
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr "Contabilización de TPV"
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr "Punto de venta"
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr "Cierre de caja TPV"
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr "Relación de sesión de TPV"
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr "Transferencia de dinero TPV"
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr "Tipo de transferencia de dinero TPV"
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr "Pago TPV"
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr "Método de pago TPV"
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr "Venta TPV"
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr "Línea de venta de TPV"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr "Cerrada"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr "Abierta"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr "Contabilizada"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr "Borrador"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr "Contabilizada"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr "Cancelada"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr "Finalizada"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr "Abierta"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr "Contabilizada"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr "General"
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr "Información adicional"
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr "Pagos"
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr "Venta"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr "Aceptar"
diff --git a/modules/sale_point/locale/es_419.po b/modules/sale_point/locale/es_419.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/es_419.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/et.po b/modules/sale_point/locale/et.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/et.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/fa.po b/modules/sale_point/locale/fa.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/fa.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/fi.po b/modules/sale_point/locale/fi.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/fi.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/fr.po b/modules/sale_point/locale/fr.po
new file mode 100644
index 0000000000..ac090d453f
--- /dev/null
+++ b/modules/sale_point/locale/fr.po
@@ -0,0 +1,680 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr "Prix brut"
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr "Modèle"
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr "Prix brut"
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr "Prix bruts"
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr "Prix brut"
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr "Prix bruts"
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr "Adresse"
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr "Emplacement de destination"
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr "Journal"
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr "Emplacement de retour"
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr "Séquence"
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr "Emplacement de stockage"
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr "Taxe incluse"
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr "Balance"
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr "Montant final"
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr "Session suivante"
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr "Paiements"
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr "Point"
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr "Session précédente"
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr "Montant de départ"
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr "Transferts"
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr "Suivante"
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr "Précédente"
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr "Mouvement"
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr "Point"
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr "Session"
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr "Journal"
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr "Espèces"
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr "Méthode"
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr "Point"
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr "État de la vente"
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr "Session"
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr "Compte"
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr "Espèces"
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr "Nom"
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr "Payé"
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr "À payer"
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr "Employé"
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr "Lignes"
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr "Mouvement"
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr "Numéro"
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr "Paiements"
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr "Point"
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr "État"
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr "Total des taxes"
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr "Montant"
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr "Société"
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr "Devise"
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr "Mouvements"
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr "Quantité"
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr "État de la vente"
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr "Unité"
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr "Prix unitaire brut"
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr "Prix unitaire listé"
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Prix unitaire"
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr "Le prix avec les taxes par défaut incluses."
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr "Le prix avec les taxes par défaut incluses."
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+"L'emplacement où les marchandises sont placées lorsqu'elles sont vendues."
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+"L'emplacement où les marchandises sont placées lors du retour.\n"
+"Si vide, l'emplacement de stockage est utilisé."
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+"L'emplacement d'où les marchandises sont prises lorsqu'elles sont vendues."
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr "Cochez si le prix unitaire comprend les taxes."
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Sessions d'encaissement de PDV"
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Types de transfert d'espèces PDV"
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Méthodes de paiement PDV"
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr "Points de vente"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr "Ventes PDV"
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr "Payer la vente PDV"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr "Toutes"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr "Clôturées"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+msgstr "Ouvertes"
+
+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_done"
+msgid "Done"
+msgstr "Terminées"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr "Ouvertes"
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr "Pour supprimer la session « %(session)s », vous devez la rouvrir."
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr "Une session ne peut être utilisée comme précédente qu'une seule fois."
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+"Pour fermer la session « %(session)s », vous devez modifier le montant final"
+" pour avoir %(amount)s au lieu de %(end_amount)s."
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+"Pour supprimer le paiement « %(payment)s » vous devez rouvrir la vente "
+"« %(sale)s »."
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Pour supprimer le paiement « %(payment)s » vous devez rouvrir la session "
+"« %(session)s »."
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+"Chaque entreprise ne peut avoir qu'un seul moyen de paiement en espèces."
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr "Chaque point de vente ne peut avoir qu'une seule session ouverte."
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+"Vous ne pouvez pas modifier l'indicateur taxe incluse du point de vente car "
+"il a des ventes."
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+"La vente « %(sale)s » est annulée et ne peut donc pas avoir de montant payé."
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+"La vente « %(sale)s » est faite et ne peut donc pas avoir de montant à "
+"payer."
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+"Vous ne pouvez pas supprimer la vente « %(sale)s » car elle a un numéro."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+"Vous ne pouvez pas supprimer le transfert « %(transfer)s » car il est posté."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Pour supprimer le transfert « %(transfer)s » vous devez rouvrir la session "
+"« %(session)s »."
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr "Êtes-vous sûr de vouloir poster les sessions ?"
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr "Êtes-vous sûr de vouloir poster le transfert ?"
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr "Êtes-vous sûr de vouloir poster les ventes ?"
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr "Clôturer"
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr "Rouvrir"
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr "Poster"
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr "Poster"
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr "Rouvrir"
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr "Payer"
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr "Poster"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Traiter"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr "Utilisateur dans les sociétés"
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr "PDV"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "Sessions d'encaissement de PDV"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "Types de transfert d'espèces PDV"
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "Méthodes de paiement PDV"
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr "Points de vente"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr "Ventes PDV"
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr "Prix brut du produit"
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr "PDV"
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr "Postage PDV"
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr "Point de vente"
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr "Sessions d'encaissement de PDV"
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr "Relation de session de point de vente"
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr "Transfert d'espèces PDV"
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr "Type de transfert d'espèces POS"
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr "Paiement PDV"
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr "Méthodes de paiement PDV"
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr "Vente PDV"
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr "Ligne de vente PDV"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr "Clôturée"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr "Ouverte"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr "Postée"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr "Brouillon"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr "Posté"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr "Annulée"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr "Terminée"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr "Ouverte"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr "Postée"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr "Général"
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr "Autre information"
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr "Paiements"
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr "Vente"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr "Annuler"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr "OK"
diff --git a/modules/sale_point/locale/hu.po b/modules/sale_point/locale/hu.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/hu.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/id.po b/modules/sale_point/locale/id.po
new file mode 100644
index 0000000000..52b9d694b2
--- /dev/null
+++ b/modules/sale_point/locale/id.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr "Alamat"
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr "Jurnal"
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr "Urutan"
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr "Lokasi Penyimpanan"
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr "Saldo"
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr "Status"
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr "Kas"
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr "Metode"
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr "Status Penjualan"
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr "Kas"
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr "Nama"
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr "Mata Uang"
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr "Tanggal"
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr "Karyawan"
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr "Nomor"
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr "Total"
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr "Perusahaan"
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr "Produk"
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Status Penjualan"
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr "Satuan"
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr "Tutup"
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Proses"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr "Pengguna di dalam perusahaan"
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr "Umum"
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr "Info Lain"
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr "Penjualan"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr "Batal"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr "OK"
diff --git a/modules/sale_point/locale/it.po b/modules/sale_point/locale/it.po
new file mode 100644
index 0000000000..a495259387
--- /dev/null
+++ b/modules/sale_point/locale/it.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr "Prezzo Lordo"
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr "Modello"
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr "Prezzo Lordo"
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr "Prezzi Lordi"
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr "Prezzo Lordo"
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr "Prezzi Lordi"
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr "A Locazione"
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Data"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr "Movimenti"
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr "Annullato"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/lo.po b/modules/sale_point/locale/lo.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/lo.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/lt.po b/modules/sale_point/locale/lt.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/lt.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/nl.po b/modules/sale_point/locale/nl.po
new file mode 100644
index 0000000000..ffbc71398a
--- /dev/null
+++ b/modules/sale_point/locale/nl.po
@@ -0,0 +1,677 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr "Bruto prijs"
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr "Sjabloon"
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr "Bruto prijs"
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr "Bruto prijs"
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr "Bruto prijs"
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr "Bruto prijs"
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr "Adres"
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr "Naar locatie"
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr "Dagboek"
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr "Retourlocatie"
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr "Reeks"
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr "Opslaglocatie"
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr "Inclusief belasting"
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr "Balans"
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr "Eindbedrag"
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr "Volgende sessie"
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr "betalingen"
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr "Vorige sessie"
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr "Startbedrag"
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr "Staat"
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr "Overboekingen"
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr "Volgende"
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr "Vorige"
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr "Boeking"
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr "Sessie"
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr "Staat"
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr "Rekening"
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr "Dagboek"
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr "Contant geld"
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr "Methode"
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr "Verkoop status"
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr "Sessie"
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr "Rekening"
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr "Contant geld"
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr "Naam"
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr "Betaald"
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr "te betalen"
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr "datum"
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr "Werknemer"
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr "Regels"
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr "Mutatie"
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr "Nummer"
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr "betalingen"
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr "Punt"
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr "Staat"
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr "Totaal"
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr "Totaal belastingen"
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr "Bedrag"
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr "Bedrijf"
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr "Mutaties"
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr "Hoeveelheid"
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr "Verkoop status"
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr "Eenheid"
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr "Brutoprijs per eenheid"
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr "eenheidsprijslijst"
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr "Eenheids- prijs"
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr "De prijs met standaard belasting inbegrepen."
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr "De prijs met standaard belasting inbegrepen."
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr "De locatie waar goederen worden geplaatst wanneer ze verkocht zijn."
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+"De plaats waar goederen bij terugkomst worden neergezet.\n"
+"Indien leeg wordt de opslaglocatie gebruikt."
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+"De locatie van waaruit goederen worden gehaald wanneer ze worden verkocht."
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr "Vink aan als de eenheidsprijs inclusief belasting is."
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "POS Cash-sessies"
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "POS kas soorten boeking"
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "POS-betaalmethoden"
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr "Verkooppunten"
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr "POS-verkoop"
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr "Betaal POS-verkoop"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr "Alle"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr "Afgesloten"
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+msgstr "Geopend"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_all"
+msgid "All"
+msgstr "Alles"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_done"
+msgid "Done"
+msgstr "Klaar"
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr "Geopend"
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr "Om sessie \"%(session)s\" te verwijderen, moet u deze opnieuw openen."
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr "Een sessie kan slechts één keer als vorige worden gebruikt."
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+"Om de sessie \"%(session)s\" te sluiten, moet je het eindbedrag wijzigen om "
+"%(amount)s te krijgen in plaats van %(end_amount)s."
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+"Om de betaling \"%(payment)s\" te verwijderen, moet u de verkoop "
+"\"%(sale)s\" opnieuw openen."
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Om de betaling \"%(payment)s\" te verwijderen, moet u de sessie "
+"\"%(session)s\" opnieuw openen."
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr "Elk bedrijf kan slechts één contante betaalmethode hebben."
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr "Elk verkooppunt kan slechts één sessie open hebben."
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+"U kunt het vinkje inclusief btw van het verkooppunt niet wijzigen omdat deze"
+" verkopen heeft."
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+"De verkoop \"%(sale)s\" is geannuleerd, er mag dus geen betaald bedrag "
+"geboekt zijn."
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+"De verkoop \"%(sale)s\" is gedaan en mag dus geen te betalen bedrag hebben."
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr "U kunt verkoop \"%(sale)s\" niet verwijderen omdat deze een nummer heeft."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+"U kunt overboeking \"%(transfer)s\" niet verwijderen omdat deze geboekt is ."
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+"Om overdracht \"%(transfer)s\" te verwijderen, moet u sessie \"%(session)s\""
+" opnieuw openen."
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr "Weet je zeker dat je de sessies wilt boeken?"
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr "Weet u zeker dat u de overboeking wilt boeken?"
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr "Weet u zeker dat u de verkopen wilt boeken?"
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr "Sluiten"
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr "Heropen"
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr "Boek"
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr "Boek"
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr "Heropen"
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr "Betalen"
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr "Boek"
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr "Verwerken"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr "Gebruiker in het bedrijf"
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.rule.group,name:rule_group_sale_companies"
+msgid "User in companies"
+msgstr "Gebruiker in bedrijven"
+
+msgctxt "model:ir.sequence.type,name:sequence_type_sale"
+msgid "POS"
+msgstr "POS"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr "POS Cash-sessies"
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr "POS kas soorten boeking"
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr "POS-betaalmethoden"
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr "Verkooppunten"
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr "POS-verkoop"
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr "Bruto productprijs"
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr "POS"
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr "POS-boeking"
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr "Verkooppunt"
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr "POS Cash-sessies"
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr "POS-sessierelatie"
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr "POS kas overboeking"
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr "POS kas soort boeking"
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr "POS-betaling"
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr "POS-betaalmethoden"
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr "POS-verkoop"
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr "POS-verkooplijn"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr "Afgesloten"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr "Open"
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr "Geboekt"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr "Concept"
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr "Geboekt"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr "Geannuleerd"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr "Klaar"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr "Open"
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr "Geboekt"
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr "Algemeen"
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr "Overige informatie"
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr "betalingen"
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr "Verkoop"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr "Annuleer"
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr "Ok"
diff --git a/modules/sale_point/locale/pl.po b/modules/sale_point/locale/pl.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/pl.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/pt.po b/modules/sale_point/locale/pt.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/pt.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/ro.po b/modules/sale_point/locale/ro.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/ro.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/ru.po b/modules/sale_point/locale/ru.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/ru.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/sl.po b/modules/sale_point/locale/sl.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/sl.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/tr.po b/modules/sale_point/locale/tr.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/tr.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/uk.po b/modules/sale_point/locale/uk.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/uk.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/locale/zh_CN.po b/modules/sale_point/locale/zh_CN.po
new file mode 100644
index 0000000000..9a5de0a99d
--- /dev/null
+++ b/modules/sale_point/locale/zh_CN.po
@@ -0,0 +1,660 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.gross_price,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:product.gross_price,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.gross_price,template:"
+msgid "Template"
+msgstr ""
+
+msgctxt "field:product.product,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.product,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:product.template,gross_price:"
+msgid "Gross Price"
+msgstr ""
+
+msgctxt "field:product.template,gross_prices:"
+msgid "Gross Prices"
+msgstr ""
+
+msgctxt "field:sale.point,address:"
+msgid "Address"
+msgstr ""
+
+msgctxt "field:sale.point,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point,customer_location:"
+msgid "To Location"
+msgstr ""
+
+msgctxt "field:sale.point,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point,return_location:"
+msgid "Return Location"
+msgstr ""
+
+msgctxt "field:sale.point,sequence:"
+msgid "Sequence"
+msgstr ""
+
+msgctxt "field:sale.point,storage_location:"
+msgid "Storage Location"
+msgstr ""
+
+msgctxt "field:sale.point,tax_included:"
+msgid "Tax Included"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,balance:"
+msgid "Balance"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,end_amount:"
+msgid "End Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,next_session:"
+msgid "Next Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,previous_session:"
+msgid "Previous Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,start_amount:"
+msgid "Start Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session,transfers:"
+msgid "Transfers"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,next:"
+msgid "Next"
+msgstr ""
+
+msgctxt "field:sale.point.cash.session.relation,previous:"
+msgid "Previous"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer,type:"
+msgid "Type"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,journal:"
+msgid "Journal"
+msgstr ""
+
+msgctxt "field:sale.point.cash.transfer.type,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.payment,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.payment,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.payment,method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.point.payment,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.payment,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.payment,session:"
+msgid "Session"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,account:"
+msgid "Account"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,cash:"
+msgid "Cash"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.payment.method,name:"
+msgid "Name"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_paid:"
+msgid "Paid"
+msgstr ""
+
+msgctxt "field:sale.point.sale,amount_to_pay:"
+msgid "To Pay"
+msgstr ""
+
+msgctxt "field:sale.point.sale,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale,date:"
+msgid "Date"
+msgstr ""
+
+msgctxt "field:sale.point.sale,employee:"
+msgid "Employee"
+msgstr ""
+
+msgctxt "field:sale.point.sale,lines:"
+msgid "Lines"
+msgstr ""
+
+msgctxt "field:sale.point.sale,move:"
+msgid "Move"
+msgstr ""
+
+msgctxt "field:sale.point.sale,number:"
+msgid "Number"
+msgstr ""
+
+msgctxt "field:sale.point.sale,payments:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "field:sale.point.sale,point:"
+msgid "Point"
+msgstr ""
+
+msgctxt "field:sale.point.sale,state:"
+msgid "State"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total:"
+msgid "Total"
+msgstr ""
+
+msgctxt "field:sale.point.sale,total_tax:"
+msgid "Total Tax"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,amount:"
+msgid "Amount"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,company:"
+msgid "Company"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,currency:"
+msgid "Currency"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,moves:"
+msgid "Moves"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,quantity:"
+msgid "Quantity"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,sale_state:"
+msgid "Sale State"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit:"
+msgid "Unit"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_gross_price:"
+msgid "Unit Gross Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_list_price:"
+msgid "Unit List Price"
+msgstr ""
+
+msgctxt "field:sale.point.sale.line,unit_price:"
+msgid "Unit Price"
+msgstr ""
+
+msgctxt "help:product.product,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:product.template,gross_price:"
+msgid "The price with default tax included."
+msgstr ""
+
+msgctxt "help:sale.point,customer_location:"
+msgid "The location where goods are put when sold."
+msgstr ""
+
+msgctxt "help:sale.point,return_location:"
+msgid ""
+"The location where goods are put when returned.\n"
+"If empty the storage location is used."
+msgstr ""
+
+msgctxt "help:sale.point,storage_location:"
+msgid "The location from where goods are taken when sold."
+msgstr ""
+
+msgctxt "help:sale.point,tax_included:"
+msgid "Check if unit Price includes tax."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.action,name:act_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:ir.action,name:wizard_pay"
+msgid "Pay POS Sale"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_all"
+msgid "All"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_closed"
+msgid "Closed"
+msgstr ""
+
+msgctxt ""
+"model:ir.action.act_window.domain,name:act_cash_session_form_domain_open"
+msgid "Opened"
+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_done"
+msgid "Done"
+msgstr ""
+
+msgctxt "model:ir.action.act_window.domain,name:act_sale_form_domain_open"
+msgid "Opened"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_delete_open"
+msgid "To delete session \"%(session)s\" you must re-open it."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_previous_unique"
+msgid "A session can be used as previous only once."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_cash_session_wrong_end_amount"
+msgid ""
+"To close session \"%(session)s\" you must change end amount to have "
+"%(amount)s instead of %(end_amount)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_sale_open"
+msgid "To delete payment \"%(payment)s\" you must re-open sale \"%(sale)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_delete_session_open"
+msgid "To delete payment \"%(payment)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_payment_method_cash_unique"
+msgid "Each company can only have one cash payment method."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_cash_session_open_unique"
+msgid "Each point of sale can only have one session open."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_point_change_tax_included"
+msgid ""
+"You cannot change the point of sale's tax included flag because it has "
+"sales."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_paid_cancelled"
+msgid "The sale \"%(sale)s\" is cancelled so cannot have amount paid."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_amount_to_pay_done_paid"
+msgid "The sale \"%(sale)s\" is done so cannot have an amount to pay."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_delete_numbered"
+msgid "You cannot delete sale \"%(sale)s\" because it has a number."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_posted"
+msgid "You cannot delete transfer \"%(transfer)s\" because it is posted."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_transfer_delete_session_open"
+msgid "To delete transfer \"%(transfer)s\" you must re-open session \"%(session)s\"."
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_session_post_button"
+msgid "Are you sure you want to post the sessions?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:cash_transfer_post_button"
+msgid "Are you sure you want to post the transfer?"
+msgstr ""
+
+msgctxt "model:ir.model.button,confirm:sale_post_button"
+msgid "Are you sure you want to post the sales?"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_close_button"
+msgid "Close"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_session_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:cash_transfer_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_cancel_button"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_open_button"
+msgid "Re-Open"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_pay_button"
+msgid "Pay"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_post_button"
+msgid "Post"
+msgstr ""
+
+msgctxt "model:ir.model.button,string:sale_process_button"
+msgid "Process"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_session_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_cash_transfer_type_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_payment_method_companies"
+msgid "User in companies"
+msgstr ""
+
+msgctxt "model:ir.rule.group,name:rule_group_point_sale_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.type,name:sequence_type_sale"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_session_form"
+msgid "POS Cash Sessions"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_cash_transfer_type_form"
+msgid "POS Cash Transfer Types"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_payment_method_form"
+msgid "POS Payment Methods"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_point_form"
+msgid "Points of Sale"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_sale_form"
+msgid "POS Sales"
+msgstr ""
+
+msgctxt "model:product.gross_price,name:"
+msgid "Product Gross Price"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point"
+msgid "POS"
+msgstr ""
+
+msgctxt "model:res.group,name:group_sale_point_posting"
+msgid "POS Posting"
+msgstr ""
+
+msgctxt "model:sale.point,name:"
+msgid "Point of Sale"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session,name:"
+msgid "POS Cash Session"
+msgstr ""
+
+msgctxt "model:sale.point.cash.session.relation,name:"
+msgid "POS Session Relation"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer,name:"
+msgid "POS Cash Transfer"
+msgstr ""
+
+msgctxt "model:sale.point.cash.transfer.type,name:"
+msgid "POS Cash Transfer Type"
+msgstr ""
+
+msgctxt "model:sale.point.payment,name:"
+msgid "POS Payment"
+msgstr ""
+
+msgctxt "model:sale.point.payment.method,name:"
+msgid "POS Payment Method"
+msgstr ""
+
+msgctxt "model:sale.point.sale,name:"
+msgid "POS Sale"
+msgstr ""
+
+msgctxt "model:sale.point.sale.line,name:"
+msgid "POS Sale Line"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Closed"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.session,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Draft"
+msgstr ""
+
+msgctxt "selection:sale.point.cash.transfer,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Cancelled"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Done"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Open"
+msgstr ""
+
+msgctxt "selection:sale.point.sale,state:"
+msgid "Posted"
+msgstr ""
+
+msgctxt "view:sale.point.sale.line:"
+msgid "General"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Other Info"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Payments"
+msgstr ""
+
+msgctxt "view:sale.point.sale:"
+msgid "Sale"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,end:"
+msgid "Cancel"
+msgstr ""
+
+msgctxt "wizard_button:sale.point.sale.pay,payment,pay:"
+msgid "OK"
+msgstr ""
diff --git a/modules/sale_point/message.xml b/modules/sale_point/message.xml
new file mode 100644
index 0000000000..ddbed08463
--- /dev/null
+++ b/modules/sale_point/message.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+ You cannot change the point of sale's tax included flag because it has sales.
+
+
+ You cannot delete sale "%(sale)s" because it has a number.
+
+
+ The sale "%(sale)s" is done so cannot have an amount to pay.
+
+
+ The sale "%(sale)s" is cancelled so cannot have amount paid.
+
+
+ To delete payment "%(payment)s" you must re-open session "%(session)s".
+
+
+ To delete payment "%(payment)s" you must re-open sale "%(sale)s".
+
+
+ Each company can only have one cash payment method.
+
+
+ Each point of sale can only have one session open.
+
+
+ A session can be used as previous only once.
+
+
+ To close session "%(session)s" you must change end amount to have %(amount)s instead of %(end_amount)s.
+
+
+ To delete session "%(session)s" you must re-open it.
+
+
+ You cannot delete transfer "%(transfer)s" because it is posted.
+
+
+ To delete transfer "%(transfer)s" you must re-open session "%(session)s".
+
+
+
diff --git a/modules/sale_point/product.py b/modules/sale_point/product.py
new file mode 100644
index 0000000000..6974447e1c
--- /dev/null
+++ b/modules/sale_point/product.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.model import ModelSQL, fields
+from trytond.modules.company.model import CompanyValueMixin
+from trytond.modules.product import price_digits, round_price
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+
+ gross_price = fields.MultiValue(fields.Numeric(
+ "Gross Price", digits=price_digits,
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ help="The price with default tax included."))
+ gross_prices = fields.One2Many(
+ 'product.gross_price', 'template', "Gross Prices")
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field == 'gross_price':
+ return pool.get('product.gross_price')
+ return super(Template, cls).multivalue_model(field)
+
+ @fields.depends(
+ 'gross_price', 'account_category', methods=['customer_taxes_used'])
+ def on_change_gross_price(self):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Tax = pool.get('account.tax')
+ if self.gross_price is None or not self.account_category:
+ return
+ today = Date.today()
+ self.list_price = round_price(Tax.reverse_compute(
+ self.gross_price,
+ self.customer_taxes_used,
+ today))
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+
+
+class GrossPrice(ModelSQL, CompanyValueMixin):
+ "Product Gross Price"
+ __name__ = 'product.gross_price'
+ template = fields.Many2One(
+ 'product.template', "Template", ondelete='CASCADE')
+ gross_price = fields.Numeric("Gross Price", digits=price_digits)
diff --git a/modules/sale_point/product.xml b/modules/sale_point/product.xml
new file mode 100644
index 0000000000..9812d0879e
--- /dev/null
+++ b/modules/sale_point/product.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ product.template
+
+ template_form
+
+
+
+ product.template
+
+ template_tree
+
+
+
diff --git a/modules/sale_point/sale.py b/modules/sale_point/sale.py
new file mode 100644
index 0000000000..52b953bfdc
--- /dev/null
+++ b/modules/sale_point/sale.py
@@ -0,0 +1,1355 @@
+# 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 sql import Literal, Union
+from sql.aggregate import Sum
+from sql.conditionals import Coalesce
+from sql.functions import CharLength
+from sql.operators import Equal
+
+from trytond.i18n import gettext
+from trytond.model import (
+ DeactivableMixin, Exclude, Index, ModelSQL, ModelView, Workflow, fields)
+from trytond.model.exceptions import AccessError
+from trytond.modules.account.tax import TaxableMixin
+from trytond.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits, round_price
+from trytond.pool import Pool
+from trytond.pyson import Bool, Eval, Id, If
+from trytond.tools import grouped_slice, reduce_ids
+from trytond.transaction import Transaction
+from trytond.wizard import Button, StateTransition, StateView, Wizard
+
+from .exceptions import SaleValidationError, SessionValidationError
+
+
+class POS(ModelSQL, ModelView):
+ "Point of Sale"
+ __name__ = 'sale.point'
+ name = fields.Char("Name", required=True)
+ company = fields.Many2One('company.company', "Company", required=True)
+ tax_included = fields.Boolean(
+ "Tax Included",
+ help="Check if unit Price includes tax.")
+ sequence = fields.Many2One(
+ 'ir.sequence.strict', "Sequence", required=True,
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ('sequence_type', '=', Id('sale_point', 'sequence_type_sale')),
+ ])
+
+ address = fields.Many2One('party.address', "Address")
+
+ storage_location = fields.Many2One(
+ 'stock.location', "Storage Location", required=True,
+ domain=[('type', '=', 'storage')],
+ help="The location from where goods are taken when sold.")
+ return_location = fields.Many2One(
+ 'stock.location', "Return Location",
+ domain=[('type', '=', 'storage')],
+ help="The location where goods are put when returned.\n"
+ "If empty the storage location is used.")
+ customer_location = fields.Many2One(
+ 'stock.location', "To Location", required=True,
+ domain=[('type', '=', 'customer')],
+ help="The location where goods are put when sold.")
+
+ journal = fields.Many2One(
+ 'account.journal', "Journal", required=True,
+ domain=[
+ ('type', '=', 'revenue'),
+ ])
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_tax_included(cls):
+ return True
+
+ @classmethod
+ def write(cls, *args):
+ pool = Pool()
+ Sale = pool.get('sale.point.sale')
+ transaction = Transaction()
+ if (transaction.user != 0
+ and transaction.context.get('_check_access')):
+ actions = iter(args)
+ for points, values in zip(actions, actions):
+ if 'tax_included' in values:
+ for sub_points in grouped_slice(points):
+ if Sale.search([
+ ('points', 'in',
+ list(map(int, sub_points))),
+ ],
+ limit=1, order=[]):
+ raise AccessError(gettext(
+ 'sale_point.msg_point_change_tax_included')
+ )
+ super().write(*args)
+
+
+class POSSale(Workflow, ModelSQL, ModelView, TaxableMixin):
+ "POS Sale"
+ __name__ = 'sale.point.sale'
+ _rec_name = 'number'
+
+ _states = {
+ 'readonly': Eval('state') != 'open',
+ }
+
+ company = fields.Many2One(
+ 'company.company', "Company", required=True, states=_states)
+ employee = fields.Many2One(
+ 'company.employee', "Employee",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ],
+ states=_states)
+ point = fields.Many2One(
+ 'sale.point', "Point", required=True, ondelete='RESTRICT',
+ states={
+ 'readonly': ((Eval('id', 0) > 0)
+ | Bool(Eval('lines', [0]))
+ | _states['readonly']),
+ },
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ])
+ number = fields.Char(
+ "Number", readonly=True,
+ states={
+ 'required': Eval('state').in_(['done', 'posted']),
+ })
+ date = fields.Date("Date", required=True, states=_states)
+ lines = fields.One2Many(
+ 'sale.point.sale.line', 'sale', "Lines",
+ states={
+ 'readonly': (~Eval('point')
+ | _states['readonly']),
+ })
+ payments = fields.One2Many(
+ 'sale.point.payment', 'sale', "Payments", states=_states)
+ total_tax = fields.Function(Monetary(
+ "Total Tax", currency='currency', digits='currency'),
+ 'on_change_with_total_tax')
+ total = fields.Function(Monetary(
+ "Total", currency='currency', digits='currency'),
+ 'on_change_with_total')
+ amount_paid = fields.Function(Monetary(
+ "Paid", currency='currency', digits='currency'),
+ 'on_change_with_amount_paid')
+ amount_to_pay = fields.Function(Monetary(
+ "To Pay", currency='currency', digits='currency'),
+ 'on_change_with_amount_to_pay')
+ state = fields.Selection([
+ ('open', "Open"),
+ ('done', "Done"),
+ ('posted', "Posted"),
+ ('cancelled', "Cancelled"),
+ ], "State", readonly=True, sort=False)
+
+ move = fields.Many2One(
+ 'account.move', "Move", readonly=True,
+ states={
+ 'invisible': ~Eval('move'),
+ })
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"), 'on_change_with_currency')
+
+ del _states
+
+ @classmethod
+ def __setup__(cls):
+ cls.number.search_unaccented = False
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.add(
+ Index(
+ t, (t.state, Index.Equality()),
+ where=t.state.in_(['open', 'done'])))
+ cls._transitions |= {
+ ('open', 'done'),
+ ('done', 'posted'),
+ ('done', 'open'),
+ ('open', 'cancelled'),
+ ('cancelled', 'open'),
+ }
+ cls._buttons.update(
+ pay={
+ 'invisible': Eval('state') != 'open',
+ 'readonly': ~Eval('amount_to_pay'),
+ 'depends': ['amount_to_pay'],
+ },
+ cancel={
+ 'invisible': Eval('state') != 'open',
+ 'depends': ['state'],
+ },
+ open={
+ 'invisible': ~Eval('state').in_(['done', 'cancelled']),
+ 'depends': ['state'],
+ },
+ process={
+ 'invisible': Eval('state') != 'open',
+ 'readonly': (
+ Bool(Eval('amount_to_pay', 0))
+ | ~Eval('lines', [-1])),
+ 'depends': ['state', 'amount_to_pay'],
+ },
+ post={
+ 'invisible': Eval('state') != 'done',
+ 'depends': ['state'],
+ },
+ )
+
+ @classmethod
+ def order_number(cls, tables):
+ table, _ = tables[None]
+ return [CharLength(table.number), table.number]
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def default_employee(cls):
+ User = Pool().get('res.user')
+
+ if Transaction().context.get('employee'):
+ return Transaction().context['employee']
+ else:
+ user = User(Transaction().user)
+ if user.employee:
+ return user.employee.id
+
+ @classmethod
+ def default_date(cls):
+ return Pool().get('ir.date').today()
+
+ @classmethod
+ def default_state(cls):
+ return 'open'
+
+ @fields.depends('company')
+ def on_change_with_currency(self, name=None):
+ if self.company and self.company.currency:
+ return self.company.currency.id
+
+ @fields.depends('lines')
+ def on_change_with_total_tax(self, name=None):
+ return sum(line.tax_amount for line in self.lines)
+
+ @fields.depends('company', 'lines')
+ def on_change_with_total(self, name=None):
+ return sum(line.gross_amount for line in self.lines)
+
+ @fields.depends('payments')
+ def on_change_with_amount_paid(self, name=None):
+ return sum(p.amount or Decimal('0') for p in self.payments)
+
+ @fields.depends(methods=[
+ 'on_change_with_total', 'on_change_with_amount_paid'])
+ def on_change_with_amount_to_pay(self, name=None):
+ return (self.on_change_with_total()
+ - self.on_change_with_amount_paid())
+
+ def get_rec_name(self, name):
+ if self.number:
+ return self.number
+ else:
+ return '(%s)' % self.id
+
+ @classmethod
+ def copy(cls, sales, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('employee')
+ default.setdefault('number')
+ default.setdefault('payments')
+ return super().copy(sales, default=default)
+
+ @classmethod
+ def delete(cls, sales):
+ for sale in sales:
+ if sale.number:
+ raise AccessError(
+ gettext('sale_point.msg_sale_delete_numbered',
+ sale=sale.rec_name))
+ super().delete(sales)
+
+ @classmethod
+ def validate(cls, sales):
+ super().validate(sales)
+ for sale in sales:
+ if sale.state in {'done', 'posted'}:
+ if sale.amount_to_pay:
+ raise SaleValidationError(gettext(
+ 'sale_point.msg_sale_amount_to_pay_done_posted',
+ sale=sale.rec_name))
+ elif sale.state == 'cancelled':
+ if sale.amount_paid:
+ raise SaleValidationError(gettext(
+ 'sale_point.msg_sale_amount_paid_cancelled',
+ sale=sale.rec_name))
+
+ @classmethod
+ @ModelView.button_action('sale_point.wizard_pay')
+ def pay(cls, sales):
+ pass
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('cancelled')
+ def cancel(cls, sales):
+ pass
+
+ @classmethod
+ @ModelView.button
+ def open(cls, sales):
+ pass
+
+ @classmethod
+ @ModelView.button
+ def process(cls, sales):
+ cls.do([sale for sale in sales if not sale.amount_to_pay])
+
+ @classmethod
+ @Workflow.transition('done')
+ def do(cls, sales):
+ for sale in sales:
+ with Transaction().set_context(company=sale.company.id):
+ sale.number = sale.point.sequence.get()
+ cls.save(sales)
+
+ @classmethod
+ @Workflow.transition('posted')
+ def post(cls, sales):
+ pool = Pool()
+ StockMove = pool.get('stock.move')
+ AccountMove = pool.get('account.move')
+
+ stock_moves = []
+ account_moves = []
+ for sale in sales:
+ assert not sale.move
+ for line in sale.lines:
+ move = line.get_stock_move()
+ if move:
+ stock_moves.append(move)
+ account_move = sale.get_account_move()
+ sale.move = account_move
+ account_moves.append(account_move)
+ if stock_moves:
+ StockMove.save(stock_moves)
+ StockMove.do(stock_moves)
+ if account_moves:
+ AccountMove.save(account_moves)
+ AccountMove.post(account_moves)
+ cls.save(sales)
+
+ def get_account_move(self):
+ 'Return account move'
+ pool = Pool()
+ Move = pool.get('account.move')
+ Period = pool.get('account.period')
+
+ period_id = Period.find(self.company.id, date=self.date)
+ lines = []
+ for line in self.lines:
+ move_lines = line.get_account_move_lines()
+ if move_lines:
+ lines.extend(move_lines)
+
+ move_lines = self.get_tax_move_lines()
+ if move_lines:
+ lines.extend(move_lines)
+
+ for payment in self.payments:
+ move_lines = payment.get_account_move_lines()
+ if move_lines:
+ lines.extend(move_lines)
+
+ move = Move()
+ move.journal = self.point.journal
+ move.period = period_id
+ move.date = self.date
+ move.origin = self
+ move.company = self.company
+ move.lines = lines
+ return move
+
+ def get_tax_move_lines(self):
+ "Return account move lines for taxes"
+ pool = Pool()
+ Line = pool.get('account.move.line')
+ TaxLine = pool.get('account.tax.line')
+
+ lines = []
+ taxes = self._get_taxes()
+
+ # Distribute rounding error from tax computation
+ tax_amount = sum(t['amount'] for t in taxes)
+ difference = self.total_tax - tax_amount
+ if difference:
+ remaining = difference
+ for tax in taxes:
+ if tax['amount']:
+ if tax_amount:
+ ratio = tax['amount'] / tax_amount
+ else:
+ ratio = 1 / len(taxes)
+ value = self.currency.round(difference * ratio)
+ tax['amount'] += value
+ remaining -= value
+ # Add remaining rounding error to the first tax
+ if remaining:
+ for tax in taxes:
+ if tax['amount']:
+ tax['amount'] += remaining
+ break
+
+ for tax in taxes:
+ amount = tax['amount']
+ if not amount:
+ continue
+ line = Line()
+ line.description = tax['description']
+ if amount >= 0:
+ line.debit, line.credit = Decimal(0), amount
+ else:
+ line.debit, line.credit = -amount, 0
+ line.account = tax['account']
+ if tax['tax']:
+ tax_line = TaxLine()
+ tax_line.amount = amount
+ tax_line.type = 'tax'
+ tax_line.tax = tax['tax']
+ line.tax_lines = [tax_line]
+ lines.append(line)
+ return lines
+
+ @property
+ def taxable_lines(self):
+ return sum((line.taxable_lines for line in self.lines), [])
+
+ @property
+ def tax_date(self):
+ return self.date
+
+
+class POSSaleLine(ModelSQL, ModelView, TaxableMixin):
+ "POS Sale Line"
+ __name__ = 'sale.point.sale.line'
+
+ _states = {
+ 'readonly': Eval('sale_state') != 'open',
+ }
+
+ sale = fields.Many2One(
+ 'sale.point.sale', "Sale", required=True, ondelete='CASCADE',
+ states=_states)
+ product = fields.Many2One(
+ 'product.product', "Product", required=True,
+ domain=[
+ ('salable', '=', True),
+ ],
+ context={
+ 'company': Eval('company'),
+ },
+ states=_states, depends={'company'})
+ quantity = fields.Float(
+ "Quantity", digits='unit', required=True, states=_states)
+ unit = fields.Function(
+ fields.Many2One('product.uom', "Unit"), 'on_change_with_unit')
+ unit_list_price = fields.Numeric(
+ "Unit List Price", digits=price_digits, required=True,
+ states={
+ 'readonly': True, # Allow client to sent value
+ })
+ unit_gross_price = fields.Numeric(
+ "Unit Gross Price", digits=price_digits, required=True,
+ states={
+ 'readonly': True, # Allow client to sent value
+ })
+ unit_price = fields.Function(fields.Numeric(
+ "Unit Price", digits=price_digits,
+ depends={'unit_list_price', 'unit_gross_price'}),
+ 'on_change_with_unit_price')
+ amount = fields.Function(Monetary(
+ "Amount", currency='currency', digits='currency'),
+ 'on_change_with_amount')
+
+ moves = fields.One2Many(
+ 'stock.move', 'origin', 'Moves', readonly=True,
+ states={
+ 'invisible': ~Eval('moves', []),
+ })
+
+ 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', searcher='search_company')
+ currency = fields.Function(
+ fields.Many2One('currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ del _states
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('sale')
+
+ @fields.depends('product')
+ def on_change_with_unit(self, name=None):
+ # TODO packaging UOM
+ if self.product:
+ return self.product.sale_uom.id
+
+ @classmethod
+ def get_sale_states(cls):
+ pool = Pool()
+ Sale = pool.get('sale.point.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(
+ 'product', 'sale', '_parent_sale.point', '_parent_sale.date',
+ methods=['on_change_with_unit_price', 'on_change_with_amount'])
+ def on_change_product(self):
+ pool = Pool()
+ Tax = pool.get('account.tax')
+ if self.product and self.sale and self.sale.point:
+ if (self.sale.point.tax_included
+ and self.product.gross_price is not None):
+ self.unit_gross_price = self.product.gross_price
+ self.unit_list_price = round_price(Tax.reverse_compute(
+ self.unit_gross_price, self.taxes,
+ date=self.sale.date))
+ else:
+ self.unit_list_price = self.product.list_price
+ taxes = Tax.compute(
+ self.taxes, self.unit_list_price, 1,
+ date=self.sale.date)
+ tax_amount = sum(t['amount'] for t in taxes)
+ self.unit_gross_price = (
+ self.unit_list_price + tax_amount).quantize(
+ Decimal(1)
+ / 10 ** self.__class__.unit_gross_price.digits[1])
+ else:
+ self.unit_gross_price = None
+ self.unit_list_price = None
+ self.unit_price = self.on_change_with_unit_price()
+ self.amount = self.on_change_with_amount()
+
+ @fields.depends('unit_list_price', 'unit_gross_price',
+ 'sale', '_parent_sale.point')
+ def on_change_with_unit_price(self, name=None):
+ if self.sale and self.sale.point:
+ if self.sale.point.tax_included:
+ return self.unit_gross_price
+ else:
+ return self.unit_list_price
+ else:
+ return
+
+ @fields.depends('currency', 'quantity', 'unit_price')
+ def on_change_with_amount(self, name=None):
+ amount = (Decimal(str(self.quantity or 0))
+ * (self.unit_price or Decimal('0')))
+ if self.currency:
+ return self.currency.round(amount)
+ return amount
+
+ @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
+
+ @classmethod
+ def search_company(cls, name, clause):
+ return [('sale.company',) + tuple(clause[1:])]
+
+ @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
+
+ @property
+ def untax_amount(self):
+ amount = (Decimal(str(self.quantity or 0))
+ * (self.unit_list_price or Decimal('0')))
+ if getattr(self, 'currency', None):
+ amount = self.currency.round(amount)
+ return amount
+
+ @property
+ def tax_amount(self):
+ amount = self.gross_amount - self.untax_amount
+ if getattr(self, 'currency', None):
+ amount = self.currency.round(amount)
+ return amount
+
+ @property
+ def gross_amount(self):
+ amount = (Decimal(str(self.quantity or 0))
+ * (self.unit_gross_price or Decimal('0')))
+ if getattr(self, 'currency', None):
+ amount = self.currency.round(amount)
+ return amount
+
+ def get_rec_name(self, name):
+ return '%s @ %s' % (self.product.rec_name, 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 copy(cls, lines, default=None):
+ if default is None:
+ default = {}
+ else:
+ default = default.copy()
+ default.setdefault('moves')
+ return super().copy(lines, default=default)
+
+ def get_stock_move(self):
+ 'Return stock move'
+ pool = Pool()
+ Move = pool.get('stock.move')
+
+ if self.product.type == 'service':
+ return
+
+ move = Move()
+ move.quantity = abs(self.quantity)
+ move.uom = self.unit
+ move.product = self.product
+ move.from_location = self.from_location
+ move.to_location = self.to_location
+ move.company = self.company
+ move.unit_price = self.unit_list_price
+ move.currency = self.currency
+ move.effective_date = self.sale.date
+ move.origin = self
+ return move
+
+ @property
+ def from_location(self):
+ if self.quantity >= 0:
+ return self.sale.point.storage_location
+ else:
+ return self.sale.point.customer_location
+
+ @property
+ def to_location(self):
+ if self.quantity >= 0:
+ return self.sale.point.customer_location
+ else:
+ return self.sale.point.return_location
+
+ def get_account_move_lines(self):
+ "Return account move lines"
+ pool = Pool()
+ Line = pool.get('account.move.line')
+ TaxLine = pool.get('account.tax.line')
+
+ line = Line()
+ if self.quantity >= 0:
+ line.debit, line.credit = Decimal(0), self.untax_amount
+ else:
+ line.debit, line.credit = -self.untax_amount, Decimal(0)
+ with Transaction().set_context(company=self.company.id):
+ line.account = self.product.account_revenue_used
+ line.origin = self
+
+ tax_lines = []
+ for tax in self._get_taxes():
+ tax_line = TaxLine()
+ tax_line.amount = tax['base']
+ tax_line.type = 'base'
+ tax_line.tax = tax['tax']
+ tax_lines.append(tax_line)
+ line.tax_lines = tax_lines
+ return [line]
+
+ @property
+ def taxes(self):
+ pool = Pool()
+ Product = pool.get('product.product')
+ with Transaction().set_context(company=self.company.id):
+ return Product(self.product).customer_taxes_used
+
+ @property
+ def taxable_lines(self):
+ return [
+ (self.taxes, self.unit_list_price, self.quantity, self.tax_date)]
+
+ @property
+ def tax_type(self):
+ if self.quantity >= 0:
+ return 'invoice'
+ else:
+ return 'credit_note'
+
+ @property
+ def tax_date(self):
+ return self.sale.date
+
+
+class POSCashSession(Workflow, ModelSQL, ModelView):
+ "POS Cash Session"
+ __name__ = 'sale.point.cash.session'
+
+ point = fields.Many2One(
+ 'sale.point', "Point", required=True, ondelete='CASCADE')
+ previous_session = fields.Many2One(
+ 'sale.point.cash.session', "Previous Session",
+ readonly=True, ondelete='RESTRICT',
+ domain=[
+ ('point', '=', Eval('point', -1)),
+ ])
+ next_session = fields.One2One(
+ 'sale.point.cash.session.relation', 'previous', 'next', "Next Session",
+ readonly=True,
+ domain=[
+ ('point', '=', Eval('point', -1)),
+ ])
+ payments = fields.One2Many(
+ 'sale.point.payment', 'session', "Payments", readonly=True,
+ domain=[
+ ('sale.point', '=', Eval('point', -1)),
+ ])
+ transfers = fields.One2Many(
+ 'sale.point.cash.transfer', 'session', "Transfers",
+ domain=[
+ ('point', '=', Eval('point', -1)),
+ ],
+ states={
+ 'readonly': ~Eval('point'),
+ })
+ start_amount = fields.Function(
+ Monetary("Start Amount", currency='currency', digits='currency'),
+ 'get_start_amount')
+ balance = fields.Function(Monetary(
+ "Balance", currency='currency', digits='currency'),
+ 'get_balance')
+ end_amount = Monetary(
+ "End Amount", currency='currency', digits='currency', required=True,
+ states={
+ 'required': Eval('state').in_(['closed', 'posted']),
+ })
+ state = fields.Selection([
+ ('open', "Open"),
+ ('closed', "Closed"),
+ ('posted', "Posted"),
+ ], "State", readonly=True, required=True, sort=False)
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_constraints = [
+ ('point_cash_session_open_unique',
+ Exclude(t, (t.point, Equal),
+ where=t.state == 'open'),
+ 'sale_point.msg_point_cash_session_open_unique'),
+ ('point_cash_session_previous_unique',
+ Exclude(t, (Coalesce(t.previous_session, -t.point), Equal)),
+ 'sale_point.msg_cash_session_previous_unique'),
+ ]
+ cls._sql_indexes.add(
+ Index(t, (t.state, Index.Equality()), where=t.state == 'open'))
+ cls._transitions |= {
+ ('open', 'closed'),
+ ('closed', 'open'),
+ ('closed', 'posted'),
+ }
+ cls._buttons.update(
+ open={
+ 'invisible': Eval('state') != 'closed',
+ 'depends': ['state'],
+ },
+ close={
+ 'pre_validate': [
+ ('end_amount', '!=', None),
+ ],
+ 'invisible': Eval('state') != 'open',
+ 'depends': ['state'],
+ },
+ post={
+ 'invisible': Eval('state') != 'closed',
+ 'depends': ['state'],
+ },
+ )
+
+ @classmethod
+ def __register__(cls, module_name):
+ super().__register__(module_name)
+ table_h = cls.__table_handler__(module_name)
+ # Migration from 6.2: add point to previous session uniqueness.
+ table_h.drop_constraint('previous_session_unique')
+
+ @classmethod
+ def default_state(cls):
+ return 'open'
+
+ @fields.depends('point')
+ def on_change_point(self):
+ if self.point:
+ last = self.__class__.search([
+ ('point', '=', self.point.id),
+ ('next_session', '=', None),
+ ], limit=1)
+ if last:
+ self.previous_session, = last
+
+ def get_start_amount(self, name):
+ if self.previous_session:
+ return self.previous_session.end_amount
+ else:
+ return Decimal(0)
+
+ @classmethod
+ def get_balance(cls, sessions, name):
+ pool = Pool()
+ Payment = pool.get('sale.point.payment')
+ Transfer = pool.get('sale.point.cash.transfer')
+ payment = Payment.__table__()
+ transfer = Transfer.__table__()
+ cursor = Transaction().connection.cursor()
+ balances = defaultdict(Decimal)
+ for sub_sessions in grouped_slice(sessions):
+ sub_ids = [s.id for s in sub_sessions]
+ query = Union(
+ payment.select(
+ payment.session.as_('session'),
+ Sum(payment.amount).as_('amount'),
+ where=reduce_ids(payment.session, sub_ids),
+ group_by=[payment.session]),
+ transfer.select(
+ transfer.session.as_('session'),
+ Sum(transfer.amount).as_('amount'),
+ where=reduce_ids(transfer.session, sub_ids),
+ group_by=[transfer.session]),
+ all_=True)
+ query = query.select(
+ query.session, Sum(query.amount),
+ group_by=[query.session])
+ cursor.execute(*query)
+ for session_id, balance in cursor:
+ if not isinstance(balance, Decimal):
+ balance = Decimal(str(balance))
+ balances[session_id] = balance
+ for session in sessions:
+ balances[session.id] = session.currency.round(balances[session.id])
+ return balances
+
+ @classmethod
+ def default_end_amount(cls):
+ return Decimal(0)
+
+ @fields.depends('point')
+ def on_change_with_currency(self, name=None):
+ if self.point:
+ return self.point.company.currency.id
+
+ @classmethod
+ @Workflow.transition('open')
+ def open(cls, sessions):
+ pass
+
+ @classmethod
+ @Workflow.transition('closed')
+ def close(cls, sessions):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ for session in sessions:
+ if session.end_amount - session.start_amount != session.balance:
+ lang = Lang.get()
+ raise SessionValidationError(gettext(
+ 'sale_point.msg_cash_session_wrong_end_amount',
+ session=session.rec_name,
+ end_amount=lang.currency(
+ session.end_amount, session.currency),
+ amount=lang.currency(
+ session.start_amount + session.balance,
+ session.currency)))
+
+ @classmethod
+ def delete(cls, sessions):
+ cls.open(sessions)
+ for session in sessions:
+ if session.state != 'open':
+ raise AccessError(
+ gettext('sale_point.msg_cash_session_delete_open',
+ session=session.rec_name))
+ super().delete(sessions)
+
+ @classmethod
+ @Workflow.transition('posted')
+ def post(cls, sessions):
+ pool = Pool()
+ Transfer = pool.get('sale.point.cash.transfer')
+ Transfer.post(sum((s.transfers for s in sessions), ()))
+
+ @classmethod
+ def get_current(cls, point):
+ sessions = cls.search([
+ ('point', '=', point.id),
+ ('state', '=', 'open'),
+ ], limit=1)
+ if sessions:
+ session, = sessions
+ else:
+ cls.lock()
+ last = cls.search([
+ ('point', '=', point.id),
+ ('next_session', '=', None),
+ ], limit=1)
+ if last:
+ last, = last
+ else:
+ last = None
+ session = cls(point=point, previous_session=last)
+ session.save()
+ return session
+
+
+class POSCashSessionRelation(ModelSQL):
+ "POS Session Relation"
+ __name__ = 'sale.point.cash.session.relation'
+
+ previous = fields.Many2One('sale.point.cash.session', "Previous")
+ next = fields.Many2One('sale.point.cash.session', "Next")
+
+ @classmethod
+ def table_query(cls):
+ pool = Pool()
+ Session = pool.get('sale.point.cash.session')
+ session = Session.__table__()
+ return session.select(
+ session.id.as_('id'),
+ session.create_date.as_('create_date'),
+ session.create_uid.as_('create_uid'),
+ session.write_date.as_('write_date'),
+ session.write_uid.as_('write_uid'),
+ session.previous_session.as_('previous'),
+ session.id.as_('next'))
+
+
+class POSPayment(ModelSQL, ModelView):
+ "POS Payment"
+ __name__ = 'sale.point.payment'
+
+ _states = {
+ 'readonly': Eval('sale_state') != 'open',
+ }
+
+ sale = fields.Many2One(
+ 'sale.point.sale', "Sale", required=True, ondelete='CASCADE',
+ states=_states)
+ method = fields.Many2One(
+ 'sale.point.payment.method', "Method", required=True,
+ domain=[
+ ('company', '=', Eval('company')),
+ If(Eval('amount', 0) < 0,
+ ('cash', '=', True),
+ ()),
+ ],
+ states=_states)
+ amount = Monetary(
+ "Amount", currency='currency', digits='currency', states=_states)
+ session = fields.Many2One(
+ 'sale.point.cash.session', "Session",
+ ondelete='RESTRICT', readonly=True,
+ domain=[
+ ('point', '=', Eval('point', -1)),
+ ],
+ states={
+ 'invisible': ~Eval('cash'),
+ 'required': Eval('cash', False),
+ })
+
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"), 'on_change_with_currency')
+ company = fields.Function(
+ fields.Many2One('company.company', "Company"),
+ 'on_change_with_company', searcher='search_company')
+ sale_state = fields.Function(fields.Selection(
+ 'get_sale_states', "Sale State"), 'on_change_with_sale_state')
+ point = fields.Function(fields.Many2One(
+ 'sale.point', "Point"), 'on_change_with_point')
+ cash = fields.Function(fields.Boolean("Cash"), 'on_change_with_cash')
+
+ del _states
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__access__.add('sale')
+
+ @fields.depends('sale', '_parent_sale.amount_to_pay')
+ def on_change_sale(self):
+ if self.sale:
+ self.amount = self.sale.amount_to_pay
+
+ @fields.depends('company')
+ def on_change_with_currency(self, name=None):
+ if self.company and self.company.currency:
+ return self.company.currency.id
+
+ @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
+
+ @classmethod
+ def search_company(cls, name, clause):
+ return [('sale.company',) + tuple(clause[1:])]
+
+ @classmethod
+ def get_sale_states(cls):
+ pool = Pool()
+ Sale = pool.get('sale.point.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.point')
+ def on_change_with_point(self, name=None):
+ if self.sale and self.sale.point:
+ return self.sale.point.id
+
+ @fields.depends('method')
+ def on_change_with_cash(self, name=None):
+ if self.method:
+ return self.method.cash
+
+ @classmethod
+ def create(cls, vlist):
+ pool = Pool()
+ Method = pool.get('sale.point.payment.method')
+ Sale = pool.get('sale.point.sale')
+ Session = pool.get('sale.point.cash.session')
+ vlist = [v.copy() for v in vlist]
+ for values in vlist:
+ if values.get('method') and values.get('sale'):
+ method = Method(values['method'])
+ if method.cash:
+ sale = Sale(values['sale'])
+ values['session'] = Session.get_current(sale.point)
+ return super().create(vlist)
+
+ @classmethod
+ def delete(cls, payments):
+ for payment in payments:
+ if payment.sale.state != 'open':
+ raise AccessError(
+ gettext('sale_point.msg_payment_delete_sale_open',
+ payment=payment.rec_name,
+ sale=payment.sale.rec_name))
+ if payment.session and payment.session.state != 'open':
+ raise AccessError(
+ gettext('sale_point.msg_payment_delete_session_open',
+ payment=payment.rec_name,
+ session=payment.session.rec_name))
+ super().delete(payments)
+
+ def get_account_move_lines(self):
+ "Return account move lines"
+ pool = Pool()
+ Line = pool.get('account.move.line')
+
+ line = Line()
+ if self.sale.total >= 0:
+ line.debit, line.credit = self.amount, Decimal(0)
+ else:
+ line.debit, line.credit = Decimal(0), -self.amount
+ line.account = self.method.account
+ line.origin = self
+ return [line]
+
+
+class POSPaymentMethod(DeactivableMixin, ModelSQL, ModelView):
+ "POS Payment Method"
+ __name__ = 'sale.point.payment.method'
+ company = fields.Many2One('company.company', "Company", required=True)
+ name = fields.Char("Name", required=True, translate=True)
+ account = fields.Many2One(
+ 'account.account', "Account", required=True,
+ domain=[
+ ('type', '!=', None),
+ ('closed', '!=', True),
+ ('company', '=', Eval('company')),
+ ])
+ cash = fields.Boolean("Cash")
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_constraints = [
+ ('cash_company_unique',
+ Exclude(t, (t.company, Equal),
+ where=(t.active == Literal(True))
+ & (t.cash == Literal(True))),
+ 'sale_point.msg_payment_method_cash_unique'),
+ ]
+ cls._order.insert(0, ('name', 'ASC'))
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+
+class POSPay(Wizard):
+ "POS Pay"
+ __name__ = 'sale.point.sale.pay'
+ start_state = 'payment'
+ payment = StateView(
+ 'sale.point.payment',
+ 'sale_point.payment_view_form_wizard', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("OK", 'pay', 'tryton-ok', default=True),
+ ])
+ pay = StateTransition()
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.__rpc__['create'].fresh_session = True
+
+ def default_payment(self, fields):
+ pool = Pool()
+ PaymentMethod = pool.get('sale.point.payment.method')
+ default = {
+ 'sale': self.record.id,
+ 'amount': self.record.amount_to_pay,
+ }
+ if default['amount'] < 0:
+ methods = PaymentMethod.search([
+ ('company', '=', self.record.company.id),
+ ('cash', '=', True),
+ ])
+ if methods:
+ method, = methods
+ default['method'] = method.id
+ return default
+
+ def transition_pay(self):
+ self.payment.sale = self.record
+ self.payment.save()
+ if self.record.amount_to_pay:
+ return 'payment'
+ else:
+ self.model.process([self.record])
+ return 'end'
+
+
+class POSCashTransfer(Workflow, ModelSQL, ModelView):
+ "POS Cash Transfer"
+ __name__ = 'sale.point.cash.transfer'
+
+ _states = {
+ 'readonly': Eval('state') == 'posted',
+ }
+
+ point = fields.Many2One(
+ 'sale.point', "Point", required=True, states=_states)
+ session = fields.Many2One(
+ 'sale.point.cash.session', "Session", required=True,
+ domain=[
+ ('point', '=', Eval('point', -1)),
+ If(Eval('state') == 'draft',
+ ('state', '=', 'open'),
+ ()),
+ ],
+ states={
+ 'required': Eval('id', -1) >= 0,
+ 'readonly': _states['readonly'],
+ 'invisible': ~Eval('point'),
+ })
+ type = fields.Many2One(
+ 'sale.point.cash.transfer.type', "Type", required=True,
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ])
+ amount = Monetary(
+ "Amount", currency='currency', digits='currency', states=_states)
+ date = fields.Date("Date", required=True)
+ state = fields.Selection([
+ ('draft', "Draft"),
+ ('posted', "Posted"),
+ ], "State", readonly=True, required=True, sort=False)
+
+ move = fields.Many2One(
+ 'account.move', "Move", readonly=True,
+ states={
+ 'invisible': ~Eval('move'),
+ })
+
+ company = fields.Function(fields.Many2One(
+ 'company.company', "Company"),
+ 'on_change_with_company')
+ currency = fields.Function(fields.Many2One(
+ 'currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ del _states
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.add(
+ Index(t, (t.state, Index.Equality()), where=t.state == 'draft'))
+ cls._transitions |= {
+ ('draft', 'posted'),
+ }
+ cls._buttons.update(
+ post={
+ 'invisible': Eval('state') != 'draft',
+ 'depends': ['state'],
+ },
+ )
+
+ @classmethod
+ def default_state(cls):
+ return 'draft'
+
+ @classmethod
+ def default_date(cls):
+ return Pool().get('ir.date').today()
+
+ @fields.depends('point')
+ def on_change_with_company(self, name=None):
+ if self.point:
+ return self.point.company.id
+
+ @fields.depends('point')
+ def on_change_with_currency(self, name=None):
+ if self.point:
+ return self.point.company.currency.id
+
+ @classmethod
+ def delete(cls, transfers):
+ for transfer in transfers:
+ if transfer.state == 'posted':
+ raise AccessError(
+ gettext('sale_point.msg_transfer_delete_posted',
+ transfer=transfer.rec_name))
+ if transfer.session.state != 'open':
+ raise AccessError(
+ gettext('sale_point.msg_transfer_delete_session_open',
+ transfer=transfer.rec_name,
+ session=transfer.session.rec_name))
+ super().delete(transfers)
+
+ @classmethod
+ @ModelView.button
+ @Workflow.transition('posted')
+ def post(cls, transfers):
+ pool = Pool()
+ Move = pool.get('account.move')
+ PaymentMethod = pool.get('sale.point.payment.method')
+
+ methods = PaymentMethod.search([('cash', '=', True)])
+ company2account = {m.company: m.account for m in methods}
+
+ moves = []
+ for transfer in transfers:
+ assert not transfer.move
+ move = transfer.get_move(
+ account=company2account.get(transfer.company))
+ transfer.move = move
+ moves.append(move)
+ Move.save(moves)
+ cls.save(transfers)
+
+ def get_move(self, account):
+ pool = Pool()
+ Line = pool.get('account.move.line')
+ Move = pool.get('account.move')
+ Period = pool.get('account.period')
+
+ period_id = Period.find(self.company.id, date=self.date)
+ line = Line()
+ if self.amount >= 0:
+ line.debit, line.credit = self.amount, Decimal(0)
+ else:
+ line.debit, line.credit = Decimal(0), -self.amount
+ line.account = account
+ counterpart = Line()
+ counterpart.debit, counterpart.credit = line.credit, line.debit
+ counterpart.account = self.type.account
+
+ move = Move()
+ move.journal = self.type.journal
+ move.period = period_id
+ move.date = self.date
+ move.origin = self
+ move.company = self.company
+ move.lines = [line, counterpart]
+ return move
+
+ @classmethod
+ def create(cls, vlist):
+ pool = Pool()
+ Point = pool.get('sale.point')
+ Session = pool.get('sale.point.cash.session')
+ vlist = [v.copy() for v in vlist]
+ for values in vlist:
+ if values.get('point') and not values.get('session'):
+ point = Point(values['point'])
+ values['session'] = Session.get_current(point)
+ return super().create(vlist)
+
+
+class POSCashTransferType(ModelSQL, ModelView):
+ "POS Cash Transfer Type"
+ __name__ = 'sale.point.cash.transfer.type'
+
+ company = fields.Many2One('company.company', "Company", required=True)
+ name = fields.Char("Name", required=True, translate=True)
+ journal = fields.Many2One(
+ 'account.journal', "Journal", required=True,
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'company'})
+ account = fields.Many2One(
+ 'account.account', "Account", required=True,
+ domain=[
+ ('type', '!=', None),
+ ('closed', '!=', True),
+ ('company', '=', Eval('company', -1)),
+ ])
+
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+# TODO: wizard to create an invoice from sale
diff --git a/modules/sale_point/sale.xml b/modules/sale_point/sale.xml
new file mode 100644
index 0000000000..bfdeeec543
--- /dev/null
+++ b/modules/sale_point/sale.xml
@@ -0,0 +1,529 @@
+
+
+
+
+
+ POS
+
+
+
+
+
+
+
+ POS Posting
+
+
+
+
+
+
+
+ POS
+
+
+
+
+
+
+
+
+
+
+
+ sale.point
+ form
+ point_form
+
+
+ sale.point
+ tree
+ point_list
+
+
+
+ Points of Sale
+ sale.point
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ sale.point.sale
+ form
+ sale_form
+
+
+ sale.point.sale
+ tree
+ sale_list
+
+
+
+ POS Sales
+ sale.point.sale
+
+
+
+
+
+
+
+
+
+
+
+
+ Opened
+
+
+
+
+
+ Done
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pay
+ Pay
+
+
+
+
+ cancel
+ Cancel
+
+
+
+
+ open
+ Re-Open
+
+
+
+
+ process
+ Process
+
+
+
+
+ post
+ Post
+ Are you sure you want to post the sales?
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ sale.point.sale.line
+ form
+ sale_line_form
+
+
+ sale.point.sale.line
+ tree
+ sale_line_list
+
+
+
+ sale.point.cash.session
+ form
+ cash_session_form
+
+
+
+ sale.point.cash.session
+ tree
+ cash_session_list
+
+
+
+ POS Cash Sessions
+ sale.point.cash.session
+
+
+
+
+
+
+
+
+
+
+
+
+ Opened
+
+
+
+
+
+ Closed
+
+
+
+
+
+ All
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ open
+ Re-Open
+
+
+
+
+ close
+ Close
+
+
+
+
+ post
+ Post
+ Are you sure you want to post the sessions?
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ sale.point.payment.method
+ form
+ payment_method_form
+
+
+ sale.point.payment.method
+ tree
+ payment_method_list
+
+
+
+ POS Payment Methods
+ sale.point.payment.method
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ sale.point.payment
+ form
+ payment_form
+
+
+ sale.point.payment
+ form
+
+ payment_form_wizard
+
+
+ sale.point.payment
+ tree
+ payment_list
+
+
+
+ Pay POS Sale
+ sale.point.sale.pay
+ sale.point.sale
+
+
+
+ sale.point.cash.transfer
+ form
+ cash_transfer_form
+
+
+
+ sale.point.cash.transfer
+ tree
+ cash_transfer_list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ post
+ Post
+ Are you sure you want to post the transfer?
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+ sale.point.cash.transfer.type
+ form
+ cash_transfer_type_form
+
+
+
+ sale.point.cash.transfer.type
+ tree
+ cash_transfer_type_list
+
+
+
+ POS Cash Transfer Types
+ sale.point.cash.transfer.type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/sale_reporting.py b/modules/sale_point/sale_reporting.py
new file mode 100644
index 0000000000..27a1e488a4
--- /dev/null
+++ b/modules/sale_point/sale_reporting.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 sql import Literal
+from sql.operators import Concat
+
+from trytond.pool import Pool
+
+
+class AbstractMixin:
+ __slots__ = ()
+
+ @classmethod
+ def _pos_sale_line(cls, length, index, company_id=None):
+ pool = Pool()
+ Company = pool.get('company.company')
+ Line = pool.get('sale.point.sale.line')
+ Point = pool.get('sale.point')
+ Sale = pool.get('sale.point.sale')
+
+ line = Line.__table__()
+ point = Point.__table__()
+ sale = Sale.__table__()
+ if company_id is not None:
+ company = Company(company_id)
+ currency_id = company.currency.id
+ else:
+ currency_id = None
+ return (line
+ .join(sale, condition=line.sale == sale.id)
+ .join(point, condition=sale.point == point.id)
+ .select(
+ (line.id * length + index).as_('id'),
+ *cls._pos_sale_line_columns(line, point, sale, currency_id),
+ where=sale.state.in_(cls._pos_sale_states())
+ & (sale.company == company_id),
+ ))
+
+ @classmethod
+ def _pos_sale_line_columns(cls, line, point, sale, currency):
+ return [
+ line.product.as_('product'),
+ line.quantity.as_('quantity'),
+ line.unit_gross_price.as_('unit_price'),
+ Concat('sale.point.sale,', line.sale).as_('order'),
+ sale.date.as_('date'),
+ sale.company.as_('company'),
+ Literal(currency).as_('currency'),
+ Literal(None).as_('customer'),
+ point.storage_location.as_('location'),
+ point.address.as_('shipment_address'),
+ ]
+
+ @classmethod
+ def _lines(cls):
+ return super()._lines() + [cls._pos_sale_line]
+
+ @classmethod
+ def _pos_sale_states(cls):
+ return ['done', 'posted']
diff --git a/modules/sale_point/setup.py b/modules/sale_point/setup.py
new file mode 100755
index 0000000000..45e1ee1d50
--- /dev/null
+++ b/modules/sale_point/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 find_packages, setup
+
+
+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_point'
+
+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 Point of 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/projects/modules-sale-point/'),
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_point',
+ },
+ keywords='tryton POS sale',
+ package_dir={'trytond.modules.sale_point': '.'},
+ packages=(
+ ['trytond.modules.sale_point']
+ + ['trytond.modules.sale_point.%s' % p for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_point': (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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_point = trytond.modules.sale_point
+ """,
+ )
diff --git a/modules/sale_point/stock.py b/modules/sale_point/stock.py
new file mode 100644
index 0000000000..498dd35364
--- /dev/null
+++ b/modules/sale_point/stock.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 PoolMeta
+
+
+class Move(metaclass=PoolMeta):
+ __name__ = 'stock.move'
+
+ @classmethod
+ def _get_origin(cls):
+ return super(Move, cls)._get_origin() + ['sale.point.sale.line']
diff --git a/modules/sale_point/tests/__init__.py b/modules/sale_point/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_point/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_point/tests/scenario_sale_point.rst b/modules/sale_point/tests/scenario_sale_point.rst
new file mode 100644
index 0000000000..7e2d707d96
--- /dev/null
+++ b/modules/sale_point/tests/scenario_sale_point.rst
@@ -0,0 +1,215 @@
+============
+POS 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, create_tax)
+ >>> from trytond.modules.account_invoice.tests.tools import (
+ ... set_fiscalyear_invoice_sequences)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_point')
+
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+ >>> StockMove = Model.get('stock.move')
+
+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)
+
+Create tax::
+
+ >>> tax = create_tax(Decimal('.21'))
+ >>> tax.save()
+
+Create account categories::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.customer_taxes.append(tax)
+ >>> 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.account_category = account_category
+ >>> template.gross_price = Decimal('12.0000')
+ >>> template.list_price
+ Decimal('9.9174')
+ >>> template.save()
+ >>> goods, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'service'
+ >>> template.default_uom = unit
+ >>> template.type = 'service'
+ >>> template.salable = True
+ >>> template.account_category = account_category
+ >>> template.list_price = Decimal('29.7520')
+ >>> template.gross_price = Decimal('36.0000')
+ >>> template.save()
+ >>> service, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create 2 payment methods::
+
+ >>> cash_method = PaymentMethod(name="Cash")
+ >>> cash_method.account = accounts['cash']
+ >>> cash_method.cash = True
+ >>> cash_method.save()
+ >>> terminal_method = PaymentMethod(name="Terminal")
+ >>> accounts['terminal'], = accounts['cash'].duplicate(
+ ... default={'name': "Terminal"})
+ >>> terminal_method.account = accounts['terminal']
+ >>> terminal_method.save()
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+
+ >>> line = sale.lines.new()
+ >>> line.product = goods
+ >>> line.unit_price
+ Decimal('12.0000')
+ >>> line.unit_list_price
+ Decimal('9.9174')
+ >>> line.unit_gross_price
+ Decimal('12.0000')
+ >>> line.quantity = 500
+ >>> line.amount
+ Decimal('6000.00')
+
+ >>> line = sale.lines.new()
+ >>> line.product = service
+ >>> line.quantity = 1
+
+ >>> sale.total
+ Decimal('6036.00')
+ >>> sale.total_tax
+ Decimal('1047.55')
+
+ >>> sale.save()
+ >>> sale.state
+ 'open'
+ >>> sale.total
+ Decimal('6036.00')
+ >>> sale.total_tax
+ Decimal('1047.55')
+
+Overpay by terminal::
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = terminal_method
+ >>> payment.form.amount
+ Decimal('6036.00')
+ >>> payment.form.amount = Decimal('6100.00')
+ >>> payment.execute('pay')
+
+ >>> payment.form.method == cash_method
+ True
+ >>> payment.form.amount
+ Decimal('-64.00')
+ >>> payment.execute('pay')
+
+ >>> sale.state
+ 'done'
+
+Post the sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
+
+Check stock move::
+
+ >>> move, = StockMove.find([
+ ... ('origin.sale', '=', sale.id, 'sale.point.sale.line')
+ ... ])
+ >>> move.product == goods
+ True
+ >>> move.quantity
+ 500.0
+ >>> move.from_location == storage_loc
+ True
+ >>> move.to_location == customer_loc
+ True
+ >>> move.state
+ 'done'
+
+Check account move::
+
+ >>> bool(sale.move)
+ True
+
+ >>> accounts['revenue'].reload()
+ >>> accounts['revenue'].debit, accounts['revenue'].credit
+ (Decimal('0.00'), Decimal('4988.45'))
+
+ >>> accounts['tax'].reload()
+ >>> accounts['tax'].debit, accounts['tax'].credit
+ (Decimal('0.00'), Decimal('1047.55'))
+
+ >>> accounts['cash'].reload()
+ >>> accounts['cash'].debit, accounts['cash'].credit
+ (Decimal('-64.00'), Decimal('0.00'))
+
+ >>> accounts['terminal'].reload()
+ >>> accounts['terminal'].debit, accounts['terminal'].credit
+ (Decimal('6100.00'), Decimal('0.00'))
diff --git a/modules/sale_point/tests/scenario_sale_point_reporting.rst b/modules/sale_point/tests/scenario_sale_point_reporting.rst
new file mode 100644
index 0000000000..5bdc9a7af4
--- /dev/null
+++ b/modules/sale_point/tests/scenario_sale_point_reporting.rst
@@ -0,0 +1,126 @@
+======================
+POS Reporting 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_point')
+
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+ >>> StockMove = Model.get('stock.move')
+
+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)
+
+Create account categories::
+
+ >>> 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.account_category = account_category
+ >>> template.gross_price = Decimal('12.0000')
+ >>> template.save()
+ >>> goods, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create a payment method::
+
+ >>> cash_method = PaymentMethod(name="Cash")
+ >>> cash_method.account = accounts['cash']
+ >>> cash_method.cash = True
+ >>> cash_method.save()
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+ >>> line = sale.lines.new()
+ >>> line.product = goods
+ >>> line.quantity = 1
+ >>> sale.save()
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = cash_method
+ >>> payment.execute('pay')
+
+Check sale reporting::
+
+ >>> Reporting = Model.get('sale.reporting.main')
+ >>> context = dict(
+ ... from_date=fiscalyear.start_date,
+ ... to_date=fiscalyear.end_date,
+ ... period='month')
+ >>> with config.set_context(context=context):
+ ... reports = Reporting.find([])
+ >>> len(reports)
+ 1
+ >>> report, = reports
+ >>> report.number
+ 1
+ >>> report.revenue == Decimal('12.00')
+ True
diff --git a/modules/sale_point/tests/scenario_sale_point_return.rst b/modules/sale_point/tests/scenario_sale_point_return.rst
new file mode 100644
index 0000000000..dac0b6d20c
--- /dev/null
+++ b/modules/sale_point/tests/scenario_sale_point_return.rst
@@ -0,0 +1,170 @@
+===================
+POS Scenario Return
+===================
+
+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, create_tax
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences
+
+Activate modules::
+
+ >>> config = activate_modules('sale_point')
+
+Get models::
+
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+
+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)
+
+Create tax::
+
+ >>> tax = create_tax(Decimal('.21'))
+ >>> tax.save()
+
+Create account categories::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.customer_taxes.append(tax)
+ >>> 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.account_category = account_category
+ >>> template.gross_price = Decimal('12.0000')
+ >>> template.list_price
+ Decimal('9.9174')
+ >>> template.save()
+ >>> goods, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> input_loc, = Location.find([('code', '=', 'IN')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.return_location = input_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create payment method::
+
+ >>> cash_method = PaymentMethod(name="Cash")
+ >>> cash_method.account = accounts['cash']
+ >>> cash_method.cash = True
+ >>> cash_method.save()
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+
+ >>> line = sale.lines.new()
+ >>> line.product = goods
+ >>> line.quantity = -1
+
+ >>> sale.save()
+ >>> sale.total
+ Decimal('-12.00')
+
+Add payment::
+
+ >>> payment = sale.payments.new()
+ >>> payment.method = cash_method
+ >>> payment.amount
+ Decimal('-12.00')
+ >>> sale.save()
+ >>> sale.amount_to_pay
+ Decimal('0.00')
+
+ >>> sale.click('process')
+ >>> sale.state
+ 'done'
+
+Post the sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
+
+Check stock move::
+
+ >>> line, = sale.lines
+ >>> move, = line.moves
+ >>> move.product == goods
+ True
+ >>> move.from_location == customer_loc
+ True
+ >>> move.to_location == input_loc
+ True
+ >>> move.state
+ 'done'
+
+Check account move::
+
+ >>> bool(sale.move)
+ True
+
+ >>> accounts['revenue'].reload()
+ >>> accounts['revenue'].debit, accounts['revenue'].credit
+ (Decimal('9.92'), Decimal('0.00'))
+
+ >>> accounts['tax'].reload()
+ >>> accounts['tax'].debit, accounts['tax'].credit
+ (Decimal('2.08'), Decimal('0.00'))
+
+ >>> accounts['cash'].reload()
+ >>> accounts['cash'].debit, accounts['cash'].credit
+ (Decimal('0.00'), Decimal('12.00'))
diff --git a/modules/sale_point/tests/scenario_sale_point_session.rst b/modules/sale_point/tests/scenario_sale_point_session.rst
new file mode 100644
index 0000000000..72a2661d9a
--- /dev/null
+++ b/modules/sale_point/tests/scenario_sale_point_session.rst
@@ -0,0 +1,180 @@
+====================
+POS Session 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, create_tax)
+ >>> from trytond.modules.account_invoice.tests.tools import (
+ ... set_fiscalyear_invoice_sequences)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_point')
+
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+ >>> Session = Model.get('sale.point.cash.session')
+ >>> TransferType = Model.get('sale.point.cash.transfer.type')
+
+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)
+
+Create account categories::
+
+ >>> 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.salable = True
+ >>> template.account_category = account_category
+ >>> template.gross_price = Decimal('20.0000')
+ >>> template.save()
+ >>> product, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create cash payment method::
+
+ >>> cash_method = PaymentMethod(name="Cash")
+ >>> cash_method.account = accounts['cash']
+ >>> cash_method.cash = True
+ >>> cash_method.save()
+
+Create transfer type::
+
+ >>> transfer_type = TransferType(name="Bank")
+ >>> transfer_type.journal, = Journal.find([('type', '=', 'cash')], limit=1)
+ >>> accounts['bank'], = accounts['cash'].duplicate(default={'name': "Bank"})
+ >>> transfer_type.account = accounts['bank']
+ >>> transfer_type.save()
+
+Create an initial cash session::
+
+ >>> session = Session(point=pos)
+ >>> transfer = session.transfers.new(point=pos)
+ >>> transfer.type = transfer_type
+ >>> transfer.amount = Decimal('100.00')
+ >>> session.end_amount = Decimal('100.00')
+ >>> session.save()
+ >>> session.start_amount
+ Decimal('0')
+ >>> session.balance
+ Decimal('100.00')
+ >>> session.end_amount
+ Decimal('100.00')
+
+ >>> session.click('close')
+ >>> session.state
+ 'closed'
+ >>> session.click('post')
+ >>> session.state
+ 'posted'
+
+ >>> transfer, = session.transfers
+ >>> transfer.state
+ 'posted'
+ >>> bool(transfer.move)
+ True
+ >>> accounts['bank'].reload()
+ >>> accounts['bank'].balance
+ Decimal('-100.00')
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 1
+ >>> sale.save()
+ >>> sale.total
+ Decimal('20.00')
+
+Pay by cash::
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = cash_method
+ >>> payment.form.amount
+ Decimal('20.00')
+ >>> payment.execute('pay')
+
+ >>> sale.state
+ 'done'
+ >>> payment, = sale.payments
+
+Check the new session::
+
+ >>> session = payment.session
+ >>> session.state
+ 'open'
+ >>> session.start_amount
+ Decimal('100.00')
+ >>> session.balance
+ Decimal('20.00')
+
+Try to close::
+
+ >>> session.click('close') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SessionValidationError: ...
+
+ >>> session.end_amount = Decimal('120.00')
+ >>> session.click('close')
+ >>> session.state
+ 'closed'
diff --git a/modules/sale_point/tests/scenario_sale_point_tax_excluded.rst b/modules/sale_point/tests/scenario_sale_point_tax_excluded.rst
new file mode 100644
index 0000000000..10f587bd7c
--- /dev/null
+++ b/modules/sale_point/tests/scenario_sale_point_tax_excluded.rst
@@ -0,0 +1,152 @@
+============
+POS 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, create_tax
+ >>> from trytond.modules.account_invoice.tests.tools import \
+ ... set_fiscalyear_invoice_sequences
+
+Activate modules::
+
+ >>> config = activate_modules('sale_point')
+
+Get models::
+
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+
+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)
+
+Create tax::
+
+ >>> tax = create_tax(Decimal('.21'))
+ >>> tax.save()
+
+Create account categories::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.customer_taxes.append(tax)
+ >>> 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('10.0000')
+ >>> template.account_category = account_category
+ >>> template.save()
+ >>> goods, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.tax_included = False
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create payment method::
+
+ >>> cash_method = PaymentMethod(name="Cash")
+ >>> cash_method.account = accounts['cash']
+ >>> cash_method.cash = True
+ >>> cash_method.save()
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+
+ >>> line = sale.lines.new()
+ >>> line.product = goods
+ >>> line.unit_price
+ Decimal('10.0000')
+ >>> line.unit_list_price
+ Decimal('10.0000')
+ >>> line.unit_gross_price
+ Decimal('12.1000')
+ >>> line.quantity = 5
+ >>> line.amount
+ Decimal('50.00')
+
+ >>> sale.total
+ Decimal('60.50')
+ >>> sale.total_tax
+ Decimal('10.50')
+
+ >>> sale.save()
+ >>> sale.state
+ 'open'
+ >>> sale.total
+ Decimal('60.50')
+ >>> sale.total_tax
+ Decimal('10.50')
+
+Add payment::
+
+ >>> payment = sale.payments.new()
+ >>> payment.method = cash_method
+ >>> sale.save()
+ >>> sale.amount_to_pay
+ Decimal('0.00')
+
+ >>> sale.click('process')
+ >>> sale.state
+ 'done'
+
+Post the sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
diff --git a/modules/sale_point/tests/test_module.py b/modules/sale_point/tests/test_module.py
new file mode 100644
index 0000000000..543dd28c94
--- /dev/null
+++ b/modules/sale_point/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class POSTestCase(ModuleTestCase):
+ "Test POS module"
+ module = 'sale_point'
+
+
+del ModuleTestCase
diff --git a/modules/sale_point/tests/test_scenario.py b/modules/sale_point/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_point/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_point/tox.ini b/modules/sale_point/tox.ini
new file mode 100644
index 0000000000..585cb40885
--- /dev/null
+++ b/modules/sale_point/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_point/* -m unittest discover -s tests
+ coverage report --include=./**/sale_point/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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_point/tryton.cfg b/modules/sale_point/tryton.cfg
new file mode 100644
index 0000000000..dee3b0388f
--- /dev/null
+++ b/modules/sale_point/tryton.cfg
@@ -0,0 +1,16 @@
+[tryton]
+version=6.7.0
+depends:
+ account
+ account_product
+ company
+ ir
+ party
+ product
+ res
+ sale
+ stock
+xml:
+ sale.xml
+ product.xml
+ message.xml
diff --git a/modules/sale_point/view/cash_session_form.xml b/modules/sale_point/view/cash_session_form.xml
new file mode 100644
index 0000000000..df3bc09459
--- /dev/null
+++ b/modules/sale_point/view/cash_session_form.xml
@@ -0,0 +1,29 @@
+
+
+
diff --git a/modules/sale_point/view/cash_session_list.xml b/modules/sale_point/view/cash_session_list.xml
new file mode 100644
index 0000000000..c723bc0372
--- /dev/null
+++ b/modules/sale_point/view/cash_session_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/cash_transfer_form.xml b/modules/sale_point/view/cash_transfer_form.xml
new file mode 100644
index 0000000000..37e85610f8
--- /dev/null
+++ b/modules/sale_point/view/cash_transfer_form.xml
@@ -0,0 +1,25 @@
+
+
+
diff --git a/modules/sale_point/view/cash_transfer_list.xml b/modules/sale_point/view/cash_transfer_list.xml
new file mode 100644
index 0000000000..b9648915b6
--- /dev/null
+++ b/modules/sale_point/view/cash_transfer_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/cash_transfer_type_form.xml b/modules/sale_point/view/cash_transfer_type_form.xml
new file mode 100644
index 0000000000..84328a197a
--- /dev/null
+++ b/modules/sale_point/view/cash_transfer_type_form.xml
@@ -0,0 +1,14 @@
+
+
+
diff --git a/modules/sale_point/view/cash_transfer_type_list.xml b/modules/sale_point/view/cash_transfer_type_list.xml
new file mode 100644
index 0000000000..3d867bbe99
--- /dev/null
+++ b/modules/sale_point/view/cash_transfer_type_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/payment_form.xml b/modules/sale_point/view/payment_form.xml
new file mode 100644
index 0000000000..4bba199a81
--- /dev/null
+++ b/modules/sale_point/view/payment_form.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/modules/sale_point/view/payment_form_wizard.xml b/modules/sale_point/view/payment_form_wizard.xml
new file mode 100644
index 0000000000..e1ffec4891
--- /dev/null
+++ b/modules/sale_point/view/payment_form_wizard.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/modules/sale_point/view/payment_list.xml b/modules/sale_point/view/payment_list.xml
new file mode 100644
index 0000000000..95becdd7cd
--- /dev/null
+++ b/modules/sale_point/view/payment_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/payment_method_form.xml b/modules/sale_point/view/payment_method_form.xml
new file mode 100644
index 0000000000..a7f4f0e5f9
--- /dev/null
+++ b/modules/sale_point/view/payment_method_form.xml
@@ -0,0 +1,17 @@
+
+
+
diff --git a/modules/sale_point/view/payment_method_list.xml b/modules/sale_point/view/payment_method_list.xml
new file mode 100644
index 0000000000..6e5a626ad9
--- /dev/null
+++ b/modules/sale_point/view/payment_method_list.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/point_form.xml b/modules/sale_point/view/point_form.xml
new file mode 100644
index 0000000000..9984aad38e
--- /dev/null
+++ b/modules/sale_point/view/point_form.xml
@@ -0,0 +1,25 @@
+
+
+
diff --git a/modules/sale_point/view/point_list.xml b/modules/sale_point/view/point_list.xml
new file mode 100644
index 0000000000..a32d317b9b
--- /dev/null
+++ b/modules/sale_point/view/point_list.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/sale_form.xml b/modules/sale_point/view/sale_form.xml
new file mode 100644
index 0000000000..373e07743d
--- /dev/null
+++ b/modules/sale_point/view/sale_form.xml
@@ -0,0 +1,47 @@
+
+
+
diff --git a/modules/sale_point/view/sale_line_form.xml b/modules/sale_point/view/sale_line_form.xml
new file mode 100644
index 0000000000..533f203259
--- /dev/null
+++ b/modules/sale_point/view/sale_line_form.xml
@@ -0,0 +1,24 @@
+
+
+
diff --git a/modules/sale_point/view/sale_line_list.xml b/modules/sale_point/view/sale_line_list.xml
new file mode 100644
index 0000000000..1f30e76351
--- /dev/null
+++ b/modules/sale_point/view/sale_line_list.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/sale_list.xml b/modules/sale_point/view/sale_list.xml
new file mode 100644
index 0000000000..5fd491b69e
--- /dev/null
+++ b/modules/sale_point/view/sale_list.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/template_form.xml b/modules/sale_point/view/template_form.xml
new file mode 100644
index 0000000000..073f8b1df3
--- /dev/null
+++ b/modules/sale_point/view/template_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_point/view/template_tree.xml b/modules/sale_point/view/template_tree.xml
new file mode 100644
index 0000000000..08f333d16b
--- /dev/null
+++ b/modules/sale_point/view/template_tree.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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_price_list/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_price_list/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_price_list/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_price_list/CHANGELOG b/modules/sale_price_list/CHANGELOG
new file mode 100644
index 0000000000..ba4f7027a0
--- /dev/null
+++ b/modules/sale_price_list/CHANGELOG
@@ -0,0 +1,88 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..df66364561
--- /dev/null
+++ b/modules/sale_price_list/COPYRIGHT
@@ -0,0 +1,16 @@
+Copyright (C) 2009-2022 Cédric Krier.
+Copyright (C) 2009-2012 Bertrand Chenal.
+Copyright (C) 2009-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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_price_list/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..ad0a00bc0c
--- /dev/null
+++ b/modules/sale_price_list/__init__.py
@@ -0,0 +1,20 @@
+# 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, party, product, sale
+
+
+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..4c4ac453c7
--- /dev/null
+++ b/modules/sale_price_list/configuration.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 ModelSQL, fields
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval
+
+
+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)),
+ ])
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..d16b857830
--- /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 "Daftar Harga Penjualan"
+
+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/uk.po b/modules/sale_price_list/locale/uk.po
new file mode 100644
index 0000000000..eb38526039
--- /dev/null
+++ b/modules/sale_price_list/locale/uk.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..87af2e5dbe
--- /dev/null
+++ b/modules/sale_price_list/party.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.
+from trytond import backend
+from trytond.model import ModelSQL, fields
+from trytond.modules.company.model import (
+ CompanyMultiValueMixin, CompanyValueMixin)
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Eval
+from trytond.tools.multivalue import migrate_property
+from trytond.transaction import Transaction
+
+
+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
+
+ @classmethod
+ def copy(cls, parties, default=None):
+ context = Transaction().context
+ default = default.copy() if default else {}
+ if context.get('_check_access'):
+ fields = ['sale_price_lists', 'sale_price_list']
+ default_values = cls.default_get(fields, with_rec_name=False)
+ for fname in fields:
+ default.setdefault(fname, default_values.get(fname))
+ return super().copy(parties, default=default)
+
+
+class PartySalePriceList(ModelSQL, CompanyValueMixin):
+ "Party Sale Price List"
+ __name__ = 'party.party.sale_price_list'
+ party = fields.Many2One(
+ 'party.party', "Party", ondelete='CASCADE',
+ context={
+ 'company': Eval('company', -1),
+ },
+ depends={'company'})
+ sale_price_list = fields.Many2One(
+ 'product.price_list', "Sale Price List",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ])
+
+ @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..173fe57028
--- /dev/null
+++ b/modules/sale_price_list/party.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ 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..a5075f174f
--- /dev/null
+++ b/modules/sale_price_list/product.py
@@ -0,0 +1,95 @@
+# 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.transaction import Transaction
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
+
+ def _get_sale_unit_price(self, quantity=0):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ 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
+ today = Date.today()
+
+ 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 and unit_price is not None:
+ unit_price = Tax.reverse_compute(
+ unit_price, taxes, today)
+ 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..1fa2ff36c0
--- /dev/null
+++ b/modules/sale_price_list/sale.py
@@ -0,0 +1,68 @@
+# 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 Bool, Equal, Eval, Not, Or
+
+
+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]))),
+ })
+
+ @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'))
+
+ @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..148432619a
--- /dev/null
+++ b/modules/sale_price_list/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_price_list = trytond.modules.sale_price_list
+ """,
+ )
diff --git a/modules/sale_price_list/tests/__init__.py b/modules/sale_price_list/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_price_list/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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..e0ca944217
--- /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(1)
+ >>> 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_module.py b/modules/sale_price_list/tests/test_module.py
new file mode 100644
index 0000000000..7a187b742d
--- /dev/null
+++ b/modules/sale_price_list/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SalePriceListTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test SalePriceList module'
+ module = 'sale_price_list'
+
+
+del ModuleTestCase
diff --git a/modules/sale_price_list/tests/test_scenario.py b/modules/sale_price_list/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_price_list/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_price_list/tox.ini b/modules/sale_price_list/tox.ini
new file mode 100644
index 0000000000..7044b2668e
--- /dev/null
+++ b/modules/sale_price_list/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_price_list/* -m unittest discover -s tests
+ coverage report --include=./**/sale_price_list/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..aa48262dd7
--- /dev/null
+++ b/modules/sale_price_list/tryton.cfg
@@ -0,0 +1,13 @@
+[tryton]
+version=6.7.0
+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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_product_customer/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_product_customer/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_product_customer/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_product_customer/CHANGELOG b/modules/sale_product_customer/CHANGELOG
new file mode 100644
index 0000000000..fd75c51e57
--- /dev/null
+++ b/modules/sale_product_customer/CHANGELOG
@@ -0,0 +1,28 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-01
+* 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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_product_customer/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..1e19b01cb1
--- /dev/null
+++ b/modules/sale_product_customer/__init__.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.pool import Pool
+
+from . import product, 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(
+ sale.LineBlanketAgreement,
+ sale.BlanketAgreementLine,
+ module='sale_product_customer', type_='model',
+ depends=['sale_blanket_agreement'])
+ 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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/bg.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..416fceba61
--- /dev/null
+++ b/modules/sale_product_customer/locale/ca.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/cs.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..b7dd47d78e
--- /dev/null
+++ b/modules/sale_product_customer/locale/de.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..5f4e671313
--- /dev/null
+++ b/modules/sale_product_customer/locale/es.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/es_419.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..c6c9168e50
--- /dev/null
+++ b/modules/sale_product_customer/locale/et.po
@@ -0,0 +1,59 @@
+#
+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"
+
+#, fuzzy
+msgctxt "field:sale.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/fa.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/fi.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..209cab01fc
--- /dev/null
+++ b/modules/sale_product_customer/locale/fr.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/hu.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..cfd2574d5b
--- /dev/null
+++ b/modules/sale_product_customer/locale/id.po
@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Pelanggan"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr ""
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produk Pelanggan"
+
+#, fuzzy
+msgctxt "field:sale.blanket_agreement.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..660f775a24
--- /dev/null
+++ b/modules/sale_product_customer/locale/it.po
@@ -0,0 +1,56 @@
+#
+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 "Prodotto del cliente"
+
+#, fuzzy
+msgctxt "field:sale.blanket_agreement.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Prodotto del cliente"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Prodotto del cliente"
+
+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"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Clienti"
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Clienti"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Cliente del prodotto"
diff --git a/modules/sale_product_customer/locale/lo.po b/modules/sale_product_customer/locale/lo.po
new file mode 100644
index 0000000000..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/lo.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/lt.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..cc7dfee5c5
--- /dev/null
+++ b/modules/sale_product_customer/locale/nl.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Product van de klant"
+
+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"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Klanten"
+
+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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/pl.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/pt.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a9c269753
--- /dev/null
+++ b/modules/sale_product_customer/locale/ro.po
@@ -0,0 +1,56 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,product_customers:"
+msgid "Customers"
+msgstr "Clienți"
+
+msgctxt "field:product.template,product_customers:"
+msgid "Customers"
+msgstr "Clienți"
+
+msgctxt "field:sale.amendment.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produsul Clientului"
+
+#, fuzzy
+msgctxt "field:sale.blanket_agreement.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produsul Clientului"
+
+msgctxt "field:sale.line,product_customer:"
+msgid "Customer's Product"
+msgstr "Produsul Clientului"
+
+msgctxt "field:sale.product_customer,code:"
+msgid "Code"
+msgstr "Cod"
+
+msgctxt "field:sale.product_customer,name:"
+msgid "Name"
+msgstr "Denumire"
+
+msgctxt "field:sale.product_customer,party:"
+msgid "Customer"
+msgstr "Client"
+
+msgctxt "field:sale.product_customer,product:"
+msgid "Variant"
+msgstr "Varianta"
+
+msgctxt "field:sale.product_customer,template:"
+msgid "Product"
+msgstr "Produs"
+
+msgctxt "model:ir.action,name:act_product_customer_form"
+msgid "Customers"
+msgstr "Clienți"
+
+msgctxt "model:ir.ui.menu,name:menu_product_customer"
+msgid "Customers"
+msgstr "Clienți"
+
+msgctxt "model:sale.product_customer,name:"
+msgid "Product Customer"
+msgstr "Produs Client"
diff --git a/modules/sale_product_customer/locale/ru.po b/modules/sale_product_customer/locale/ru.po
new file mode 100644
index 0000000000..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/ru.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/sl.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/tr.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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/uk.po b/modules/sale_product_customer/locale/uk.po
new file mode 100644
index 0000000000..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/uk.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..8a2d17e4be
--- /dev/null
+++ b/modules/sale_product_customer/locale/zh_CN.po
@@ -0,0 +1,55 @@
+#
+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.blanket_agreement.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..230c0fae48
--- /dev/null
+++ b/modules/sale_product_customer/product.py
@@ -0,0 +1,163 @@
+# 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 (
+ DeactivableMixin, MatchMixin, ModelSQL, ModelView, fields,
+ sequence_ordered)
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Bool, Eval, If
+from trytond.tools import is_full_text, 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',
+ domain=[
+ If(Bool(Eval('product')),
+ ('products', '=', Eval('product')),
+ ()),
+ If(Eval('active'), ('active', '=', True), ()),
+ ])
+ product = fields.Many2One(
+ 'product.product', "Variant",
+ domain=[
+ If(Bool(Eval('template')),
+ ('template', '=', Eval('template')),
+ ()),
+ If(Eval('active'), ('active', '=', True), ()),
+ ])
+ 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):
+ _, operator, operand, *extra = clause
+ if operator.startswith('!') or operator.startswith('not '):
+ bool_op = 'AND'
+ else:
+ bool_op = 'OR'
+ code_value = operand
+ if operator.endswith('like') and is_full_text(operand):
+ code_value = lstrip_wildcard(operand)
+ return [bool_op,
+ ('template', operator, operand, *extra),
+ ('product', operator, operand, *extra),
+ ('party', operator, operand, *extra),
+ ('code', operator, code_value, *extra),
+ ('name', operator, operand, *extra),
+ ]
+
+
+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), ()),
+ ])
+
+ 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),
+ })
+
+ 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..0c783a5efa
--- /dev/null
+++ b/modules/sale_product_customer/sale.py
@@ -0,0 +1,208 @@
+# 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 Bool, Eval, If
+
+
+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={'sale'})
+
+ @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',
+ })
+
+ @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
+
+
+class LineBlanketAgreement(metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+ @classmethod
+ def _domain_blanket_agreemnt_line_product(cls):
+ return [
+ super()._domain_blanket_agreemnt_line_product(),
+ If(Eval('product_customer'),
+ ('product_customer', '=', Eval('product_customer')),
+ ()),
+ ]
+
+ @fields.depends(
+ 'blanket_agreement_line', 'product_customer',
+ '_parent_blanket_agreement_line.product_customer')
+ def on_change_blanket_agreement_line(self):
+ if self.blanket_agreement_line:
+ line = self.blanket_agreement_line
+ if not self.product_customer:
+ self.product_customer = line.product_customer
+ super().on_change_blanket_agreement_line()
+
+
+class BlanketAgreementLine(metaclass=PoolMeta):
+ __name__ = 'sale.blanket_agreement.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_blanket_agreement', {}).get(
+ 'customer')),
+ ],
+ states={
+ 'readonly': Eval('agreement_state') != 'draft'
+ })
+
+ @fields.depends('blanket_agreement', '_parent_blanket_agreement.customer')
+ def _get_product_customer_pattern(self):
+ return {
+ 'party': (
+ self.blanket_agreement.customer.id
+ if self.blanket_agreement and self.blanket_agreement.customer
+ else -1),
+ }
+
+ @fields.depends('product', 'product_customer')
+ def on_change_product(self):
+ try:
+ super().on_change_product()
+ except AttributeError:
+ pass
+ 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()
+
+ def get_sale_line(self, sale):
+ sale_line = super().get_sale_line(sale)
+ if self.product_customer:
+ sale_line.product_customer = self.product_customer
+ return sale_line
diff --git a/modules/sale_product_customer/sale.xml b/modules/sale_product_customer/sale.xml
new file mode 100644
index 0000000000..916a25fea2
--- /dev/null
+++ b/modules/sale_product_customer/sale.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+ 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
+
+
+
+
+
+ sale.blanket_agreement.line
+
+ sale_blanket_agreement_line_form
+
+
+ sale.blanket_agreement.line
+
+ sale_blanket_agreement_line_list
+
+
+
diff --git a/modules/sale_product_customer/setup.py b/modules/sale_product_customer/setup.py
new file mode 100755
index 0000000000..829708cf87
--- /dev/null
+++ b/modules/sale_product_customer/setup.py
@@ -0,0 +1,155 @@
+#!/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 find_packages, setup
+
+
+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'),
+ get_require_version('trytond_sale_blanket_agreement'),
+ ]
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_product_customer = trytond.modules.sale_product_customer
+ """,
+ )
diff --git a/modules/sale_product_customer/tests/__init__.py b/modules/sale_product_customer/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_product_customer/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_product_customer/tests/test_module.py
new file mode 100644
index 0000000000..81e0fe7f9b
--- /dev/null
+++ b/modules/sale_product_customer/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleProductCustomerTestCase(ModuleTestCase):
+ 'Test Sale Product Customer module'
+ module = 'sale_product_customer'
+ extras = ['sale_amendment', 'sale_blanket_agreement']
+
+
+del ModuleTestCase
diff --git a/modules/sale_product_customer/tests/test_scenario.py b/modules/sale_product_customer/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_product_customer/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_product_customer/tox.ini b/modules/sale_product_customer/tox.ini
new file mode 100644
index 0000000000..2b10116b35
--- /dev/null
+++ b/modules/sale_product_customer/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_product_customer/* -m unittest discover -s tests
+ coverage report --include=./**/sale_product_customer/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..7cda7371eb
--- /dev/null
+++ b/modules/sale_product_customer/tryton.cfg
@@ -0,0 +1,12 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ product
+ sale
+extras_depend:
+ sale_amendment
+ sale_blanket_agreement
+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_blanket_agreement_line_form.xml b/modules/sale_product_customer/view/sale_blanket_agreement_line_form.xml
new file mode 100644
index 0000000000..45cdb4b14d
--- /dev/null
+++ b/modules/sale_product_customer/view/sale_blanket_agreement_line_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_customer/view/sale_blanket_agreement_line_list.xml b/modules/sale_product_customer/view/sale_blanket_agreement_line_list.xml
new file mode 100644
index 0000000000..ee37f784c2
--- /dev/null
+++ b/modules/sale_product_customer/view/sale_blanket_agreement_line_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
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..9bce7c5245
--- /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..9bce7c5245
--- /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_product_quantity/.drone.yml b/modules/sale_product_quantity/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale_product_quantity/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_product_quantity/.flake8 b/modules/sale_product_quantity/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_product_quantity/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_product_quantity/.isort.cfg b/modules/sale_product_quantity/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_product_quantity/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_product_quantity/CHANGELOG b/modules/sale_product_quantity/CHANGELOG
new file mode 100644
index 0000000000..7a287d58a2
--- /dev/null
+++ b/modules/sale_product_quantity/CHANGELOG
@@ -0,0 +1,7 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+--------------------------
+* Initial release
diff --git a/modules/sale_product_quantity/COPYRIGHT b/modules/sale_product_quantity/COPYRIGHT
new file mode 100644
index 0000000000..f8f170606e
--- /dev/null
+++ b/modules/sale_product_quantity/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2022 B2CK
+Copyright (C) 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_product_quantity/LICENSE b/modules/sale_product_quantity/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_product_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_product_quantity/MANIFEST.in b/modules/sale_product_quantity/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_product_quantity/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_product_quantity/README.rst b/modules/sale_product_quantity/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_product_quantity/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_product_quantity/__init__.py b/modules/sale_product_quantity/__init__.py
new file mode 100644
index 0000000000..ec4c098bcf
--- /dev/null
+++ b/modules/sale_product_quantity/__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 product, sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ product.Template,
+ product.Product,
+ sale.Line,
+ module='sale_product_quantity', type_='model')
+ Pool.register(
+ sale.POSLine,
+ module='sale_product_quantity', type_='model', depends=['sale_point'])
diff --git a/modules/sale_product_quantity/doc/conf.py b/modules/sale_product_quantity/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_product_quantity/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_product_quantity/doc/design.rst b/modules/sale_product_quantity/doc/design.rst
new file mode 100644
index 0000000000..65775740a0
--- /dev/null
+++ b/modules/sale_product_quantity/doc/design.rst
@@ -0,0 +1,19 @@
+******
+Design
+******
+
+The *Sale Product Quantity Module* extends the following concepts.
+
+.. _concept-product:
+
+Product
+=======
+
+When the *Sale Product Quantity Module* is activated, products gain some extra properties.
+These include a minimal and rounding quantity which are enforced on the `Sale
+` lines.
+
+.. seealso::
+
+ The `Product ` concept is introduced by the
+ :doc:`Product Module `.
diff --git a/modules/sale_product_quantity/doc/index.rst b/modules/sale_product_quantity/doc/index.rst
new file mode 100644
index 0000000000..2f4fcaea26
--- /dev/null
+++ b/modules/sale_product_quantity/doc/index.rst
@@ -0,0 +1,12 @@
+############################
+Sale Product Quantity Module
+############################
+
+The *Sale Product Quantity Module* permits to enforce the minimal and the
+rounding of quantity sold per product.
+
+.. toctree::
+ :maxdepth: 2
+
+ design
+ releases
diff --git a/modules/sale_product_quantity/doc/releases.rst b/modules/sale_product_quantity/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_product_quantity/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_product_quantity/locale/bg.po b/modules/sale_product_quantity/locale/bg.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/bg.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/ca.po b/modules/sale_product_quantity/locale/ca.po
new file mode 100644
index 0000000000..7ab1f7edc1
--- /dev/null
+++ b/modules/sale_product_quantity/locale/ca.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Dígits de la quantitat de venda"
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Quantitat mínima de venda"
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Arrodoniment de la quantitat de venda"
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Dígits de la quantitat de venda"
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Quantitat mínima de venda"
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Arrodoniment de la quantitat de venda"
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+"La quantitat %(quantity)s de la línia %(line)s és massa petita, ha de ser "
+"com a mínim %(minimum)s."
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
+"La quantitat %(quantity)s de la línia %(line)s no es vàlida, ha de ser "
+"múltiple de %(rounding)s."
diff --git a/modules/sale_product_quantity/locale/cs.po b/modules/sale_product_quantity/locale/cs.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/cs.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/de.po b/modules/sale_product_quantity/locale/de.po
new file mode 100644
index 0000000000..8d8e1da98a
--- /dev/null
+++ b/modules/sale_product_quantity/locale/de.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Nachkommastellen Verkaufsmenge"
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Verkauf Mindestabnahmemenge"
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Verkauf Rundungsmenge"
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Nachkommastellen Verkaufsmenge"
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Verkauf Mindestabnahmemenge"
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Verkauf Rundungsmenge"
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+"Die Menge %(quantity)s von Verkaufsposition %(line)s ist zu niedrig und muss"
+" auf mindestens %(minimum)s erhöht werden."
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
+"Die Menge %(quantity)s von Verkaufsposition %(line)s ist ungültig und muss "
+"ein Vielfaches von %(rounding)s sein."
diff --git a/modules/sale_product_quantity/locale/es.po b/modules/sale_product_quantity/locale/es.po
new file mode 100644
index 0000000000..aab20fda4f
--- /dev/null
+++ b/modules/sale_product_quantity/locale/es.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Dígitos de la cantidad de venta"
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Cantidad mínima de venta"
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Redondeo cantidad venta"
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Dígitos de la cantidad de venta"
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Cantidad mínima de venta"
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Redondeo cantidad venta"
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+"La cantidad %(quantity)s de la línea %(line)s es demasiado pequeña, debe ser"
+" al menos %(minimum)s."
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
+"La cantidad %(quantity)s de la línea %(line)s no es válida, debe ser "
+"múltiple de %(rounding)s."
diff --git a/modules/sale_product_quantity/locale/es_419.po b/modules/sale_product_quantity/locale/es_419.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/es_419.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/et.po b/modules/sale_product_quantity/locale/et.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/et.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/fa.po b/modules/sale_product_quantity/locale/fa.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/fa.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/fi.po b/modules/sale_product_quantity/locale/fi.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/fi.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/fr.po b/modules/sale_product_quantity/locale/fr.po
new file mode 100644
index 0000000000..76d7c13103
--- /dev/null
+++ b/modules/sale_product_quantity/locale/fr.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Décimales de quantité de vente"
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Quantité minimale de vente"
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Quantité d'arrondi de vente"
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Décimales de quantité de vente"
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Quantité minimale de vente"
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Quantité d'arrondi de vente"
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+"La quantité %(quantity)s de la ligne %(line)s est trop petite, vous devez "
+"mettre au moins %(minimum)s."
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
+"La quantité %(quantity)s de la ligne %(line)s n'est pas valide, vous devez "
+"utiliser un multiple de %(rounding)s."
diff --git a/modules/sale_product_quantity/locale/hu.po b/modules/sale_product_quantity/locale/hu.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/hu.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/id.po b/modules/sale_product_quantity/locale/id.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/id.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/it.po b/modules/sale_product_quantity/locale/it.po
new file mode 100644
index 0000000000..212472502c
--- /dev/null
+++ b/modules/sale_product_quantity/locale/it.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Decimali della quantià di vendita"
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Quantità minima di vendita"
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Quantità di arrotondamento vendita"
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Decimali della quantià di vendita"
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Quantità minima di vendita"
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Quantità di arrotondamento vendita"
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+"La quantità %(quantity)s della riga %(line)s è troppo piccola, devi "
+"impostare almeno %(minimum)s."
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
+"La quantità %(quantity)s della riga %(line)s non è valida, è necessario "
+"impostare multipli di %(rounding)s."
diff --git a/modules/sale_product_quantity/locale/lo.po b/modules/sale_product_quantity/locale/lo.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/lo.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/lt.po b/modules/sale_product_quantity/locale/lt.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/lt.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/nl.po b/modules/sale_product_quantity/locale/nl.po
new file mode 100644
index 0000000000..a540026084
--- /dev/null
+++ b/modules/sale_product_quantity/locale/nl.po
@@ -0,0 +1,43 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Aantal decimalen verkoop"
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Minimale hoeveelheid verkoop"
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Afronding hoeveelheid verkoop"
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr "Aantal decimalen verkoop"
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr "Minimale hoeveelheid verkoop"
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr "Afronding hoeveelheid verkoop"
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+"Het aantal %(quantity)s van regel %(line)s is te klein, het moet minimaal "
+"%(minimum)s zijn."
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
+"Het aantal %(quantity)s van regel %(line)s is niet geldig, het moet een "
+"veelvoud zijn van %(rounding)s."
diff --git a/modules/sale_product_quantity/locale/pl.po b/modules/sale_product_quantity/locale/pl.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/pl.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/pt.po b/modules/sale_product_quantity/locale/pt.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/pt.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/ro.po b/modules/sale_product_quantity/locale/ro.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/ro.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/ru.po b/modules/sale_product_quantity/locale/ru.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/ru.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/sl.po b/modules/sale_product_quantity/locale/sl.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/sl.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/tr.po b/modules/sale_product_quantity/locale/tr.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/tr.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/uk.po b/modules/sale_product_quantity/locale/uk.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/uk.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/locale/zh_CN.po b/modules/sale_product_quantity/locale/zh_CN.po
new file mode 100644
index 0000000000..3d5d121769
--- /dev/null
+++ b/modules/sale_product_quantity/locale/zh_CN.po
@@ -0,0 +1,39 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.product,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_digits:"
+msgid "Sale Quantity Digits"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_minimal:"
+msgid "Sale Minimal Quantity"
+msgstr ""
+
+msgctxt "field:product.template,sale_quantity_rounding:"
+msgid "Sale Rounding Quantity"
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_minimal"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is too small, you must set at "
+"least %(minimum)s."
+msgstr ""
+
+msgctxt "model:ir.message,text:msg_sale_line_quantity_rounding"
+msgid ""
+"The quantity %(quantity)s of line %(line)s is not valid, you must set "
+"multiple of %(rounding)s."
+msgstr ""
diff --git a/modules/sale_product_quantity/message.xml b/modules/sale_product_quantity/message.xml
new file mode 100644
index 0000000000..a20bd18af4
--- /dev/null
+++ b/modules/sale_product_quantity/message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ The quantity %(quantity)s of line %(line)s is too small, you must set at least %(minimum)s.
+
+
+ The quantity %(quantity)s of line %(line)s is not valid, you must set multiple of %(rounding)s.
+
+
+
diff --git a/modules/sale_product_quantity/product.py b/modules/sale_product_quantity/product.py
new file mode 100644
index 0000000000..efda5723ec
--- /dev/null
+++ b/modules/sale_product_quantity/product.py
@@ -0,0 +1,51 @@
+# 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 Pool, PoolMeta
+from trytond.pyson import Eval
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+
+ sale_quantity_minimal = fields.Float(
+ "Sale Minimal Quantity",
+ digits=(16, Eval('sale_quantity_digits', 0)),
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ domain=['OR',
+ ('sale_quantity_minimal', '=', None),
+ ('sale_quantity_minimal', '>', 0),
+ ])
+ sale_quantity_rounding = fields.Float(
+ "Sale Rounding Quantity",
+ digits=(16, Eval('sale_quantity_digits', 0)),
+ states={
+ 'invisible': ~Eval('salable', False),
+ },
+ domain=['OR',
+ ('sale_quantity_rounding', '=', None),
+ ('sale_quantity_rounding', '>', 0),
+ ])
+ sale_quantity_digits = fields.Function(
+ fields.Integer("Sale Quantity Digits"),
+ 'on_change_with_sale_quantity_digits')
+
+ @fields.depends('default_uom', 'sale_uom')
+ def on_change_with_sale_quantity_digits(self, name=None):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if self.default_uom:
+ rounding = self.default_uom.rounding
+ if self.sale_uom:
+ rounding = Uom.compute_qty(
+ self.default_uom, rounding, self.sale_uom, round=False)
+ return -Decimal(str(rounding)).as_tuple().exponent
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
diff --git a/modules/sale_product_quantity/product.xml b/modules/sale_product_quantity/product.xml
new file mode 100644
index 0000000000..3aa9317ca9
--- /dev/null
+++ b/modules/sale_product_quantity/product.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ product.template
+
+ product_template_form
+
+
+
diff --git a/modules/sale_product_quantity/sale.py b/modules/sale_product_quantity/sale.py
new file mode 100644
index 0000000000..465b7ab8ce
--- /dev/null
+++ b/modules/sale_product_quantity/sale.py
@@ -0,0 +1,87 @@
+# 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 ModelStorage, fields
+from trytond.modules.sale.exceptions import SaleValidationError
+from trytond.pool import Pool, PoolMeta
+
+
+def product_quantity_mixin(states):
+ class ProductQuantityMixin(ModelStorage):
+
+ @fields.depends('product', 'quantity', 'unit')
+ def on_change_product(self):
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ super().on_change_product()
+ if self.product and self.quantity is None:
+ if self.unit:
+ unit = self.unit
+ else:
+ unit = self.product.sale_uom
+ if self.product.sale_quantity_minimal:
+ self.quantity = Uom.compute_qty(
+ self.product.sale_uom,
+ self.product.sale_quantity_minimal,
+ unit)
+
+ @classmethod
+ def validate(cls, lines):
+ super().validate(lines)
+ for line in lines:
+ line.check_quantity()
+
+ def check_quantity(self):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ Uom = pool.get('product.uom')
+ if (not self.product
+ or self.sale.state not in states
+ or self.quantity < 0):
+ return
+ lang = Lang.get()
+ quantity = Uom.compute_qty(
+ self.unit, self.quantity, self.product.sale_uom, round=False)
+ if self.product.sale_quantity_minimal:
+ if quantity < self.product.sale_quantity_minimal:
+ minimum = Uom.compute_qty(
+ self.product.sale_uom,
+ self.product.sale_quantity_minimal,
+ self.unit)
+ raise SaleValidationError(gettext(
+ 'sale_product_quantity'
+ '.msg_sale_line_quantity_minimal',
+ line=self.rec_name,
+ quantity=lang.format_number_symbol(
+ self.quantity, self.unit),
+ minimum=lang.format_number_symbol(
+ minimum, self.unit)))
+ if self.product.sale_quantity_rounding:
+ remainder = round(
+ quantity % self.product.sale_quantity_rounding,
+ self.product.sale_quantity_digits)
+ if (remainder
+ and remainder != self.product.sale_quantity_rounding):
+ rounding = Uom.compute_qty(
+ self.product.sale_uom,
+ self.product.sale_quantity_rounding,
+ self.unit, round=False)
+ raise SaleValidationError(gettext(
+ 'sale_product_quantity'
+ '.msg_sale_line_quantity_rounding',
+ line=self.rec_name,
+ quantity=lang.format_number_symbol(
+ self.quantity, self.unit),
+ rounding=lang.format_number_symbol(
+ rounding, self.unit)))
+
+ return ProductQuantityMixin
+
+
+class Line(product_quantity_mixin(['draft']), metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+
+class POSLine(product_quantity_mixin(['open']), metaclass=PoolMeta):
+ __name__ = 'sale.point.sale.line'
diff --git a/modules/sale_product_quantity/setup.py b/modules/sale_product_quantity/setup.py
new file mode 100755
index 0000000000..09f6381cd5
--- /dev/null
+++ b/modules/sale_product_quantity/setup.py
@@ -0,0 +1,159 @@
+#!/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 find_packages, setup
+
+
+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_product_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_sale_point'),
+ ]
+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 quantity constraints 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/projects/modules-sale-product-quantity'),
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": 'https://hg.tryton.org/modules/sale_product_quantity',
+ },
+ keywords='tryton sale product quantity',
+ package_dir={'trytond.modules.sale_product_quantity': '.'},
+ packages=(
+ ['trytond.modules.sale_product_quantity']
+ + ['trytond.modules.sale_product_quantity.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_product_quantity': (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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_product_quantity = trytond.modules.sale_product_quantity
+ """, # noqa: E501
+ )
diff --git a/modules/sale_product_quantity/tests/__init__.py b/modules/sale_product_quantity/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_product_quantity/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_product_quantity/tests/scenario_sale_product_quantity.rst b/modules/sale_product_quantity/tests/scenario_sale_product_quantity.rst
new file mode 100644
index 0000000000..27147b86b8
--- /dev/null
+++ b/modules/sale_product_quantity/tests/scenario_sale_product_quantity.rst
@@ -0,0 +1,101 @@
+==============================
+Sale Product Quantity 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_quantity')
+
+ >>> Party = Model.get('party.party')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.sale')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create parties::
+
+ >>> customer = Party(name="Customer")
+ >>> customer.save()
+
+Create product::
+
+ >>> gr, = ProductUom.find([('name', '=', "Gram")])
+ >>> kg, = ProductUom.find([('name', '=', "Kilogram")])
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Product"
+ >>> template.default_uom = gr
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('10')
+ >>> template.salable = True
+ >>> template.sale_uom = kg
+ >>> template.sale_quantity_minimal = 0.1
+ >>> template.sale_quantity_rounding = 0.05
+ >>> template.save()
+ >>> product, = template.products
+
+Make a sale::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity
+ 0.1
+ >>> sale.save()
+
+Can not set quantity below minimal::
+
+ >>> line, = sale.lines
+ >>> line.quantity = 0.05
+ >>> sale.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SaleValidationError: ...
+
+Can not set quantity different than rounding::
+
+ >>> line, = sale.lines
+ >>> line.quantity = 1.01
+ >>> sale.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SaleValidationError: ...
+
+Use different unit::
+
+ >>> line, = sale.lines
+ >>> line.unit = gr
+ >>> line.quantity = 500
+ >>> sale.save()
+
+Can not set quantity below minimal::
+
+ >>> line, = sale.lines
+ >>> line.quantity = 50
+ >>> sale.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SaleValidationError: ...
+
+Can not set quantity different than rounding::
+
+ >>> line, = sale.lines
+ >>> line.quantity = 505
+ >>> sale.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SaleValidationError: ...
diff --git a/modules/sale_product_quantity/tests/scenario_sale_product_quantity_pos.rst b/modules/sale_product_quantity/tests/scenario_sale_product_quantity_pos.rst
new file mode 100644
index 0000000000..70326d4c48
--- /dev/null
+++ b/modules/sale_product_quantity/tests/scenario_sale_product_quantity_pos.rst
@@ -0,0 +1,98 @@
+==================================
+Sale Product Quantity POS 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_quantity', 'sale_point'])
+
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> Party = Model.get('party.party')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUom = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create product::
+
+ >>> gr, = ProductUom.find([('name', '=', "Gram")])
+ >>> kg, = ProductUom.find([('name', '=', "Kilogram")])
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Product"
+ >>> template.default_uom = gr
+ >>> template.type = 'goods'
+ >>> template.list_price = Decimal('10')
+ >>> template.salable = True
+ >>> template.sale_uom = kg
+ >>> template.sale_quantity_minimal = 0.1
+ >>> template.sale_quantity_rounding = 0.05
+ >>> template.save()
+ >>> product, = template.products
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity
+ 0.1
+ >>> sale.save()
+
+Can not set quantity below minimal::
+
+ >>> line, = sale.lines
+ >>> line.quantity = 0.05
+ >>> sale.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SaleValidationError: ...
+
+Can not set quantity different than rounding::
+
+ >>> line, = sale.lines
+ >>> line.quantity = 1.01
+ >>> sale.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ SaleValidationError: ...
diff --git a/modules/sale_product_quantity/tests/test_module.py b/modules/sale_product_quantity/tests/test_module.py
new file mode 100644
index 0000000000..42d5cc185d
--- /dev/null
+++ b/modules/sale_product_quantity/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleProductQuantityTestCase(ModuleTestCase):
+ 'Test Sale Product Quantity module'
+ module = 'sale_product_quantity'
+ extras = ['sale_point']
+
+
+del ModuleTestCase
diff --git a/modules/sale_product_quantity/tests/test_scenario.py b/modules/sale_product_quantity/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_product_quantity/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_product_quantity/tox.ini b/modules/sale_product_quantity/tox.ini
new file mode 100644
index 0000000000..c993cc49d8
--- /dev/null
+++ b/modules/sale_product_quantity/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_product_quantity/* -m unittest discover -s tests
+ coverage report --include=./**/sale_product_quantity/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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_quantity/tryton.cfg b/modules/sale_product_quantity/tryton.cfg
new file mode 100644
index 0000000000..c802fd7389
--- /dev/null
+++ b/modules/sale_product_quantity/tryton.cfg
@@ -0,0 +1,9 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ product
+ sale
+xml:
+ product.xml
+ message.xml
diff --git a/modules/sale_product_quantity/view/product_template_form.xml b/modules/sale_product_quantity/view/product_template_form.xml
new file mode 100644
index 0000000000..86ccfd6920
--- /dev/null
+++ b/modules/sale_product_quantity/view/product_template_form.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_recommendation/.drone.yml b/modules/sale_product_recommendation/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale_product_recommendation/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_product_recommendation/.flake8 b/modules/sale_product_recommendation/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_product_recommendation/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_product_recommendation/.isort.cfg b/modules/sale_product_recommendation/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_product_recommendation/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_product_recommendation/CHANGELOG b/modules/sale_product_recommendation/CHANGELOG
new file mode 100644
index 0000000000..7762ad3c72
--- /dev/null
+++ b/modules/sale_product_recommendation/CHANGELOG
@@ -0,0 +1,3 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+Initial release
diff --git a/modules/sale_product_recommendation/COPYRIGHT b/modules/sale_product_recommendation/COPYRIGHT
new file mode 100644
index 0000000000..f8f170606e
--- /dev/null
+++ b/modules/sale_product_recommendation/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2022 B2CK
+Copyright (C) 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_product_recommendation/LICENSE b/modules/sale_product_recommendation/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_product_recommendation/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_recommendation/MANIFEST.in b/modules/sale_product_recommendation/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_product_recommendation/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_product_recommendation/README.rst b/modules/sale_product_recommendation/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_product_recommendation/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_product_recommendation/__init__.py b/modules/sale_product_recommendation/__init__.py
new file mode 100644
index 0000000000..2afa794f75
--- /dev/null
+++ b/modules/sale_product_recommendation/__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 product, sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ product.Template,
+ product.Product,
+ sale.Configuration,
+ sale.ConfigurationProductRecommendation,
+ sale.Sale,
+ module='sale_product_recommendation', type_='model')
+ Pool.register(
+ sale.POSSale,
+ module='sale_product_recommendation', type_='model',
+ depends=['sale_point'])
diff --git a/modules/sale_product_recommendation/doc/conf.py b/modules/sale_product_recommendation/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_product_recommendation/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_product_recommendation/doc/index.rst b/modules/sale_product_recommendation/doc/index.rst
new file mode 100644
index 0000000000..1ee30d138f
--- /dev/null
+++ b/modules/sale_product_recommendation/doc/index.rst
@@ -0,0 +1,12 @@
+##################################
+Sale Product Recommendation Module
+##################################
+
+The *Sale Product Recommendation Module* provides facilities to implement
+recommendation of products on sale.
+
+.. toctree::
+ :maxdepth: 2
+
+ usage
+ releases
diff --git a/modules/sale_product_recommendation/doc/releases.rst b/modules/sale_product_recommendation/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_product_recommendation/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_product_recommendation/doc/usage.rst b/modules/sale_product_recommendation/doc/usage.rst
new file mode 100644
index 0000000000..363a6c2a56
--- /dev/null
+++ b/modules/sale_product_recommendation/doc/usage.rst
@@ -0,0 +1,14 @@
+*****
+Usage
+*****
+
+Configuration of product recommendation can be found under the
+[:menuselection:`Sales --> Configuration`] menu item.
+
+.. _Exclude product from recommendation:
+
+Exclude product from recommendation
+===================================
+
+By default all salable `Products ` can be recommended.
+If you want to exclude a product, you can uncheck the recommendable checkbox.
diff --git a/modules/sale_product_recommendation/locale/bg.po b/modules/sale_product_recommendation/locale/bg.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/bg.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/ca.po b/modules/sale_product_recommendation/locale/ca.po
new file mode 100644
index 0000000000..6d61f4d39d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/ca.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr "Recomanable"
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr "Recomanable"
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr "Mètode"
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr "Mida"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr "Métode de recomanació de productes"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr "Mida"
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Productes recomanats"
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Productes recomanats"
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr "Recomanació de producte"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr "Recomanació de producte"
diff --git a/modules/sale_product_recommendation/locale/cs.po b/modules/sale_product_recommendation/locale/cs.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/cs.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/de.po b/modules/sale_product_recommendation/locale/de.po
new file mode 100644
index 0000000000..eb11c1cd03
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/de.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr "Empfehlenswert"
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr "Empfehlenswert"
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr "Methode"
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr "Größe"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr "Artikelempfehlungsmethode"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr "Größe"
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Empfohlene Artikel"
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Empfohlene Artikel"
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr "Artikelempfehlung"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr "Artikelempfehlung"
diff --git a/modules/sale_product_recommendation/locale/es.po b/modules/sale_product_recommendation/locale/es.po
new file mode 100644
index 0000000000..4d1ccfa54a
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/es.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr "Recomendable"
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr "Recomendable"
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr "Método"
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr "Tamaño"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr "Método de recomendación de producto"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr "Tamaño"
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Productos recomendados"
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Productos recomendados"
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr "Recomendación de producto"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr "Recomendación de producto"
diff --git a/modules/sale_product_recommendation/locale/es_419.po b/modules/sale_product_recommendation/locale/es_419.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/es_419.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/et.po b/modules/sale_product_recommendation/locale/et.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/et.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/fa.po b/modules/sale_product_recommendation/locale/fa.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/fa.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/fi.po b/modules/sale_product_recommendation/locale/fi.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/fi.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/fr.po b/modules/sale_product_recommendation/locale/fr.po
new file mode 100644
index 0000000000..0c1a84f7b9
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/fr.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr "Recommandable"
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr "Recommandable"
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr "Méthode"
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr "Taille"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr "Méthode de recommandation de produit"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr "Taille"
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Produits Recommandés"
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Produits Recommandés"
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr "Recommandation de produit"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr "Recommandation de produit"
diff --git a/modules/sale_product_recommendation/locale/hu.po b/modules/sale_product_recommendation/locale/hu.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/hu.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/id.po b/modules/sale_product_recommendation/locale/id.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/id.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/it.po b/modules/sale_product_recommendation/locale/it.po
new file mode 100644
index 0000000000..647672a4b2
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/it.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr "Raccomandabile"
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr "Raccomandabile"
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr "Metodo"
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr "Dimensione"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr "Metodo di raccomandazione del prodotto"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr "Dimensione"
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Prodotti consigliati"
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Prodotti consigliati"
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr "Raccomandazione del prodotto"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr "Raccomandazione del prodotto"
diff --git a/modules/sale_product_recommendation/locale/lo.po b/modules/sale_product_recommendation/locale/lo.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/lo.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/lt.po b/modules/sale_product_recommendation/locale/lt.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/lt.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/nl.po b/modules/sale_product_recommendation/locale/nl.po
new file mode 100644
index 0000000000..af8502173b
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/nl.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr "Aanbevelen"
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr "Aanbevelen"
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr "Methode"
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr "Grootte"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr "Aanbevelingsmethode Product"
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr "Grootte"
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Aanbevolen producten"
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr "Aanbevolen producten"
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr "Productaanbeveling"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr "Productaanbeveling"
diff --git a/modules/sale_product_recommendation/locale/pl.po b/modules/sale_product_recommendation/locale/pl.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/pl.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/pt.po b/modules/sale_product_recommendation/locale/pt.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/pt.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/ro.po b/modules/sale_product_recommendation/locale/ro.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/ro.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/ru.po b/modules/sale_product_recommendation/locale/ru.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/ru.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/sl.po b/modules/sale_product_recommendation/locale/sl.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/sl.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/tr.po b/modules/sale_product_recommendation/locale/tr.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/tr.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/uk.po b/modules/sale_product_recommendation/locale/uk.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/uk.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/locale/zh_CN.po b/modules/sale_product_recommendation/locale/zh_CN.po
new file mode 100644
index 0000000000..100a6b7b6d
--- /dev/null
+++ b/modules/sale_product_recommendation/locale/zh_CN.po
@@ -0,0 +1,45 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:product.product,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:product.template,recommendable:"
+msgid "Recommendable"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_method:"
+msgid "Method"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_method:"
+msgid "Product Recommendation Method"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration.product_recommendation,product_recommendation_size:"
+msgid "Size"
+msgstr ""
+
+msgctxt "field:sale.point.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "field:sale.sale,recommended_products:"
+msgid "Recommended Products"
+msgstr ""
+
+msgctxt "model:sale.configuration.product_recommendation,name:"
+msgid "Product Recommendation"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation"
+msgstr ""
diff --git a/modules/sale_product_recommendation/product.py b/modules/sale_product_recommendation/product.py
new file mode 100644
index 0000000000..e8a591b4a8
--- /dev/null
+++ b/modules/sale_product_recommendation/product.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.
+
+from trytond.model import fields
+from trytond.pool import PoolMeta
+from trytond.pyson import Eval
+
+
+class Template(metaclass=PoolMeta):
+ __name__ = 'product.template'
+
+ recommendable = fields.Boolean(
+ "Recommendable",
+ states={
+ 'invisible': ~Eval('salable'),
+ })
+
+ @classmethod
+ def default_recommendable(cls):
+ return True
+
+
+class Product(metaclass=PoolMeta):
+ __name__ = 'product.product'
diff --git a/modules/sale_product_recommendation/product.xml b/modules/sale_product_recommendation/product.xml
new file mode 100644
index 0000000000..ca8ac9bcbe
--- /dev/null
+++ b/modules/sale_product_recommendation/product.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ product.template
+
+ product_template_form
+
+
+ product.template
+
+ product_template_list
+
+
+
diff --git a/modules/sale_product_recommendation/sale.py b/modules/sale_product_recommendation/sale.py
new file mode 100644
index 0000000000..179f729e60
--- /dev/null
+++ b/modules/sale_product_recommendation/sale.py
@@ -0,0 +1,104 @@
+# 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 Pool, PoolMeta
+from trytond.pyson import Eval
+
+product_recommendation_method = fields.Selection([
+ (None, ""),
+ ], "Method")
+product_recommendation_size = fields.Integer(
+ "Size", required=True,
+ domain=[
+ ('product_recommendation_size', '>=', 0),
+ ])
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ product_recommendation_method = fields.MultiValue(
+ product_recommendation_method)
+ product_recommendation_size = fields.MultiValue(
+ product_recommendation_size)
+
+ @classmethod
+ def default_product_recommendation_size(cls, **pattern):
+ return (
+ cls.multivalue_model('product_recommendation_size')
+ .default_product_recommendation_size())
+
+ @classmethod
+ def multivalue_model(cls, field):
+ pool = Pool()
+ if field in {
+ 'product_recommendation_method',
+ 'product_recommendation_size',
+ }:
+ return pool.get('sale.configuration.product_recommendation')
+ return super().multivalue_model(field)
+
+
+class ConfigurationProductRecommendation(ModelSQL, ValueMixin):
+ "Product Recommendation"
+ __name__ = 'sale.configuration.product_recommendation'
+
+ product_recommendation_method = fields.Selection(
+ 'get_product_recommendation_methods', "Product Recommendation Method")
+ product_recommendation_size = product_recommendation_size
+
+ @classmethod
+ def get_product_recommendation_methods(cls):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ field_name = 'product_recommendation_method'
+ return Configuration.fields_get(
+ [field_name])[field_name]['selection']
+
+ @classmethod
+ def default_product_recommendation_size(cls):
+ return 5
+
+
+class SaleMixin:
+ __slots__ = ()
+
+ recommended_products = fields.Function(fields.Many2Many(
+ 'product.product', None, None, "Recommended Products",
+ states={
+ 'invisible': (
+ (Eval('state') != 'draft')
+ | ~Eval('recommended_products')),
+ }),
+ 'on_change_with_recommended_products')
+
+ @fields.depends('state')
+ def on_change_with_recommended_products(self, name=None):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+ if self.state != 'draft':
+ return []
+ config = Configuration(1)
+ method = config.get_multivalue('product_recommendation_method')
+ size = config.get_multivalue('product_recommendation_size')
+ product_ids = []
+ if method:
+ products = getattr(self, '_recommended_products_%s' % method)()
+ for product in filter(self._is_recommendable_product, products):
+ product_ids.append(product.id)
+ if len(product_ids) >= size:
+ break
+ return product_ids
+
+ @classmethod
+ def _is_recommendable_product(cls, product):
+ return product.salable and product.recommendable
+
+
+class Sale(SaleMixin, metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+
+class POSSale(SaleMixin, metaclass=PoolMeta):
+ __name__ = 'sale.point.sale'
diff --git a/modules/sale_product_recommendation/sale.xml b/modules/sale_product_recommendation/sale.xml
new file mode 100644
index 0000000000..500dc27545
--- /dev/null
+++ b/modules/sale_product_recommendation/sale.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
+ sale.sale
+
+ sale_form
+
+
+
+
+ sale.point.sale
+
+ sale_form
+
+
+
diff --git a/modules/sale_product_recommendation/setup.py b/modules/sale_product_recommendation/setup.py
new file mode 100755
index 0000000000..a80f3b8d61
--- /dev/null
+++ b/modules/sale_product_recommendation/setup.py
@@ -0,0 +1,158 @@
+#!/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 find_packages, setup
+
+
+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_product_recommendation'
+
+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('trytond_sale_point')]
+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 product recommendation',
+ 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-product-recommendation'),
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": (
+ 'https://hg.tryton.org/modules/sale_product_recommendation'),
+ },
+ keywords='tryton sale product recommendation',
+ package_dir={'trytond.modules.sale_product_recommendation': '.'},
+ packages=(
+ ['trytond.modules.sale_product_recommendation']
+ + ['trytond.modules.sale_product_recommendation.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_product_recommendation': (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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_product_recommendation = trytond.modules.sale_product_recommendation
+ """, # noqa: E501
+ )
diff --git a/modules/sale_product_recommendation/tests/__init__.py b/modules/sale_product_recommendation/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_product_recommendation/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_product_recommendation/tests/test_module.py b/modules/sale_product_recommendation/tests/test_module.py
new file mode 100644
index 0000000000..d0401d89cb
--- /dev/null
+++ b/modules/sale_product_recommendation/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleProductRecommendationTestCase(ModuleTestCase):
+ "Test Sale Product Recommendation module"
+ module = 'sale_product_recommendation'
+ extras = ['sale_point']
+
+
+del ModuleTestCase
diff --git a/modules/sale_product_recommendation/tox.ini b/modules/sale_product_recommendation/tox.ini
new file mode 100644
index 0000000000..395ebe0c86
--- /dev/null
+++ b/modules/sale_product_recommendation/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_product_recommendation/* -m unittest discover -s tests
+ coverage report --include=./**/sale_product_recommendation/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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_recommendation/tryton.cfg b/modules/sale_product_recommendation/tryton.cfg
new file mode 100644
index 0000000000..138c443ea8
--- /dev/null
+++ b/modules/sale_product_recommendation/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ product
+ sale
+extras_depend:
+ sale_point
+xml:
+ product.xml
+ sale.xml
diff --git a/modules/sale_product_recommendation/view/configuration_form.xml b/modules/sale_product_recommendation/view/configuration_form.xml
new file mode 100644
index 0000000000..b626517d44
--- /dev/null
+++ b/modules/sale_product_recommendation/view/configuration_form.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_recommendation/view/product_template_form.xml b/modules/sale_product_recommendation/view/product_template_form.xml
new file mode 100644
index 0000000000..c31bce71d9
--- /dev/null
+++ b/modules/sale_product_recommendation/view/product_template_form.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_recommendation/view/product_template_list.xml b/modules/sale_product_recommendation/view/product_template_list.xml
new file mode 100644
index 0000000000..5d0868f131
--- /dev/null
+++ b/modules/sale_product_recommendation/view/product_template_list.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_product_recommendation/view/sale_form.xml b/modules/sale_product_recommendation/view/sale_form.xml
new file mode 100644
index 0000000000..893c8c0909
--- /dev/null
+++ b/modules/sale_product_recommendation/view/sale_form.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/modules/sale_product_recommendation_association_rule/.drone.yml b/modules/sale_product_recommendation_association_rule/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_product_recommendation_association_rule/.flake8 b/modules/sale_product_recommendation_association_rule/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_product_recommendation_association_rule/.isort.cfg b/modules/sale_product_recommendation_association_rule/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_product_recommendation_association_rule/CHANGELOG b/modules/sale_product_recommendation_association_rule/CHANGELOG
new file mode 100644
index 0000000000..7762ad3c72
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/CHANGELOG
@@ -0,0 +1,3 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+Initial release
diff --git a/modules/sale_product_recommendation_association_rule/COPYRIGHT b/modules/sale_product_recommendation_association_rule/COPYRIGHT
new file mode 100644
index 0000000000..f8f170606e
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2022 B2CK
+Copyright (C) 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_product_recommendation_association_rule/LICENSE b/modules/sale_product_recommendation_association_rule/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/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_recommendation_association_rule/MANIFEST.in b/modules/sale_product_recommendation_association_rule/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_product_recommendation_association_rule/README.rst b/modules/sale_product_recommendation_association_rule/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_product_recommendation_association_rule/__init__.py b/modules/sale_product_recommendation_association_rule/__init__.py
new file mode 100644
index 0000000000..f477bcfa16
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/__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 ir, sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ ir.Cron,
+ sale.Configuration,
+ sale.Sale,
+ sale.ProductAssociationRule,
+ sale.ProductAssociationRuleAntecedent,
+ sale.ProductAssociationRuleConsequent,
+ module='sale_product_recommendation_association_rule', type_='model')
+ Pool.register(
+ sale.ProductAssociationRulePOS,
+ module='sale_product_recommendation_association_rule', type_='model',
+ depends=['sale_point'])
diff --git a/modules/sale_product_recommendation_association_rule/doc/conf.py b/modules/sale_product_recommendation_association_rule/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/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_product_recommendation_association_rule/doc/design.rst b/modules/sale_product_recommendation_association_rule/doc/design.rst
new file mode 100644
index 0000000000..83fa28053f
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/doc/design.rst
@@ -0,0 +1,34 @@
+******
+Design
+******
+
+The *Sale Product Recommendation Association Rule Module* introduces the
+following concepts.
+
+.. _model-sale.product.association.rule:
+
+Product Association Rule
+========================
+
+The model is used to store the rules learned by the system.
+They are composed of antecedents and consequents which are lists of `Products
+`.
+The antecedents is that items that can be found in the data while the
+consequents are the items found when combined with the antecedents.
+
+The rule stores also various measures like the *confidence*, *support*, *lift*
+and *conviction*.
+
+.. seealso::
+
+ You can learn more on `association rule learning
+ `_
+
+.. seealso::
+
+ Rules are found by opening the menu item:
+
+ |Products --> Products --> Sale Association Rules|__
+
+ .. |Products --> Products --> Sale Association Rules| replace:: :menuselection:`Products --> Products --> Sale Association Rules`
+ __ https://demo.tryton.org/model/sale.product.association.rule
diff --git a/modules/sale_product_recommendation_association_rule/doc/index.rst b/modules/sale_product_recommendation_association_rule/doc/index.rst
new file mode 100644
index 0000000000..d27fa2ce96
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/doc/index.rst
@@ -0,0 +1,15 @@
+###################################################
+Sale Product Recommendation Association Rule Module
+###################################################
+
+The *Sale Product Recommendation Association Rule Module* implements
+recommendation based on `association rule learning
+`_ from previous
+sales.
+
+.. toctree::
+ :maxdepth: 2
+
+ usage
+ design
+ releases
diff --git a/modules/sale_product_recommendation_association_rule/doc/releases.rst b/modules/sale_product_recommendation_association_rule/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_product_recommendation_association_rule/doc/usage.rst b/modules/sale_product_recommendation_association_rule/doc/usage.rst
new file mode 100644
index 0000000000..1ba9e7e1e9
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/doc/usage.rst
@@ -0,0 +1,17 @@
+*****
+Usage
+*****
+
+In order to make recommendations the `Product Association Rules
+` must be computed.
+
+.. _Compute product association rules:
+
+Compute product association rules
+=================================
+
+You may want to schedule the computation of rules based on previous `Sales
+` using a scheduled task *Compute Sale Product
+Association Rules*.
+In order to select the sales used, you must define a delay in the
+`Configuration `.
diff --git a/modules/sale_product_recommendation_association_rule/ir.py b/modules/sale_product_recommendation_association_rule/ir.py
new file mode 100644
index 0000000000..c44c96556e
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/ir.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 PoolMeta
+
+
+class Cron(metaclass=PoolMeta):
+ __name__ = 'ir.cron'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.method.selection.append(
+ ('sale.product.association.rule|compute',
+ "Compute Sale Product Association Rules"))
diff --git a/modules/sale_product_recommendation_association_rule/locale/bg.po b/modules/sale_product_recommendation_association_rule/locale/bg.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/bg.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/ca.po b/modules/sale_product_recommendation_association_rule/locale/ca.po
new file mode 100644
index 0000000000..ea60856baa
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/ca.po
@@ -0,0 +1,135 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr "El número màxim de productes d'una regla."
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr "Confiança mínima"
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr "Suport mínim"
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr "Transaciones fins a"
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr "Antecedents"
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr "Antecedents"
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr "Confiança"
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr "Conseqüents"
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr "Conseqüents"
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr "Convicació"
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr "Elevador"
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr "Suport"
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr "Regla"
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr "Producte"
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr "Regla"
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr "La probabilitat mínima de la regla."
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+"La freqüència mínima en que els articles de la regla apareixen junts en el "
+"conjunt de dades."
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr "Probabilitat dels conseqüents, donats els antecedents."
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr "La freqüència en que la regla fa una predicció incorrecta."
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+"Se es igual a 1, les dos ocurrències són independents l'una de l'altra.\n"
+"Si es més gran que un, el grau en que les dos ocurrències són dependents l'una de l'altra.\n"
+"Si es menor que un, els articles són substituts l'un de l'altre."
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+"La freqüència en que els conseqüents i els antecedents apareixen junts."
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Regles d'associació de venda"
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Regles d'associació de venda"
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr "Regles d'associació de productes"
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr "Antecedents de les regles d'assocació de productes"
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr "Conseqüents de les regles d'associació de productes"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr "Calcula les regles d'associació de vendes de productes"
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr "Regla d'associació"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr "Regla d'associació de recomanació de productes"
diff --git a/modules/sale_product_recommendation_association_rule/locale/cs.po b/modules/sale_product_recommendation_association_rule/locale/cs.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/cs.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/de.po b/modules/sale_product_recommendation_association_rule/locale/de.po
new file mode 100644
index 0000000000..6881ef4ddc
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/de.po
@@ -0,0 +1,136 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr "Die maximale Anzahl von Artikeln für eine Regel."
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr "Mindestkonfidenz"
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr "Mindestsupport"
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr "Transaktionszeitraum"
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr "Ursächliche Artikel"
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr "Ursächliche Artikel"
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr "Konfidenz"
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr "Folgeartikel"
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr "Folgeartikel"
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr "Conviction"
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr "Lift"
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr "Support"
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr "Regel"
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr "Artikel"
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr "Regel"
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr "Die minimale Schwelle der Konfidenz in der Regel."
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+"Die minimale Häufigkeit mit der die Elemente aus den Daten zum Erfüllen der "
+"Regel mindestens gemeinsam auftreten müssen."
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr "Die Häufigkeit der Folgeartikel bei gegebenen ursächlichen Artikeln."
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr "Die Häufigkeit mit der die Regel falsche Vorhersagen trifft."
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+"Wenn gleich 1, dann sind die beiden Elemente unabhängig voneinander.\n"
+"Wenn größer 1, dann gibt der Wert den Grad der Abhängigkeit der beiden Elemente an.\n"
+"Wenn kleiner 1, dann sind die beiden Elemente austauschbar."
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+"Die Häufigkeit mit der ursächliche Artikel zusammen mit Folgeartikeln "
+"auftreten."
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Verkauf Assoziationsregeln"
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Verkauf Assoziationsregeln"
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr "Artikel Assoziationsregel"
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr "Artikel Assoziationsregel ursächliche Artikel"
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr "Artikel Assoziationsregel Folgeartikel"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr "Verkauf - Assoziationsregeln generieren"
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr "Assoziationsregel"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr "Assoziationsregeln für Artikelempfehlungen"
diff --git a/modules/sale_product_recommendation_association_rule/locale/es.po b/modules/sale_product_recommendation_association_rule/locale/es.po
new file mode 100644
index 0000000000..0177191f6f
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/es.po
@@ -0,0 +1,135 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr "El número máximo de producto de una regla."
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr "Confianza mínima"
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr "Soporte mínimo"
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr "Transaciones hasta"
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr "Antecedentes"
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr "Antecedentes"
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr "Confianza"
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr "Consecuentes"
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr "Consecuentes"
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr "Convicción"
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr "Elevador"
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr "Soporte"
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr "Regla"
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr "Producto"
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr "Regla"
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr "La probabilidad mínima de la regla."
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+"La frequencia mínima en que los articulos en la regla aparecen juntos en el "
+"conjunto de datos."
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr "Probabilidad de los consecuentes, dados los antecedentes."
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr "La frequencia en que la regla hace una prección incorrecta."
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+"Si es igual a 1, las dos ocurrencias són independienes una de la otra.\n"
+"Si es mayor que uno, el grado en que las dos ocurrencias son dependencias una de la otra.\n"
+"Si es menor que uno, los articulos són un sustituo uno del otro."
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+"La frecuencia en la que los consecuentes y los antecedentes aparecen juntos."
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Reglas de associación de venta"
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Reglas de associación de venta"
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr "Reglas de associación de productos"
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr "Antecedentes reglas de asociación de productos"
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr "Consiguientes reglas de asociación de productos"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr "Calcular reglas de asociacion de ventas de productos"
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr "Regla de asociación"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr "Regla de asociación de recomendaciones de producto"
diff --git a/modules/sale_product_recommendation_association_rule/locale/es_419.po b/modules/sale_product_recommendation_association_rule/locale/es_419.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/es_419.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/et.po b/modules/sale_product_recommendation_association_rule/locale/et.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/et.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/fa.po b/modules/sale_product_recommendation_association_rule/locale/fa.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/fa.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/fi.po b/modules/sale_product_recommendation_association_rule/locale/fi.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/fi.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/fr.po b/modules/sale_product_recommendation_association_rule/locale/fr.po
new file mode 100644
index 0000000000..d49a7f0246
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/fr.po
@@ -0,0 +1,134 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr "Le nombre maximal de produits pour une règle."
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr "Confiance minimale"
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr "Support minimal"
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr "Transactions jusqu'à"
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr "Antécédents"
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr "Antécédents"
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr "Confiance"
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr "Conséquents"
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr "Conséquents"
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr "Conviction"
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr "Haussement"
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr "Soutien"
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr "Règle"
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr "Produit"
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr "Règle"
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr "La probabilité minimale de la règle."
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+"La fréquence minimale à laquelle les éléments de la règle apparaissent "
+"ensemble dans l'ensemble de données."
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr "Probabilité de conséquents, étant donné les antécédents."
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr "La fréquence à laquelle la règle fait une prédiction incorrecte."
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+"Si égal à 1, les deux occurrences sont indépendantes l'une de l'autre.\n"
+"Si supérieur à 1, le degré auquel les deux occurrences dépendent l'une de l'autre.\n"
+"S'il est inférieur à 1, les éléments se substituent les uns aux autres."
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr "La fréquence des conséquents et des antécédents apparaît ensemble."
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Règles de l'association de vente"
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Règles de l'association de vente"
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr "Règle d'association de produits"
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr "Antécédent de la règle d'association de produits"
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr "Conséquent de la règle d'association de produits"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr "Calculer les règles d'association des produits de vente"
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr "Règle d'association"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr "Règle d'association de recommandation de produit"
diff --git a/modules/sale_product_recommendation_association_rule/locale/hu.po b/modules/sale_product_recommendation_association_rule/locale/hu.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/hu.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/id.po b/modules/sale_product_recommendation_association_rule/locale/id.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/id.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/it.po b/modules/sale_product_recommendation_association_rule/locale/it.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/it.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/lo.po b/modules/sale_product_recommendation_association_rule/locale/lo.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/lo.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/lt.po b/modules/sale_product_recommendation_association_rule/locale/lt.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/lt.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/nl.po b/modules/sale_product_recommendation_association_rule/locale/nl.po
new file mode 100644
index 0000000000..a68b6a7c3a
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/nl.po
@@ -0,0 +1,135 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr "Maximaal aantal producten voor een regel."
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr "Minimale zekerheid"
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr "Minimale ondersteuning"
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr "Transacties Tot"
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr "Antecedenten"
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr "Antecedenten"
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr "Zekerheid"
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr "Gevolgen"
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr "Gevolgen"
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr "Oordeel"
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr "Stijging"
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr "Ondersteuning"
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr "Regel"
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr "Product"
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr "Regel"
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr "Minimale kans van de regel."
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+"Het minimale aantal keren dat de items van de regel samen in een data set "
+"voorkomen."
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr "Aannemelijk gevolg gegeven de antecedenten."
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr "Het aantal keren dat de regel een onjuiste voorspelling doet."
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+"Gelijk aan 1, de twee weergaves zijn onafhankelijk van elkaar.\n"
+"Groter dan 1, de mate hoe de twee weergaves afhankelijk zijn van elkaar.\n"
+"Kleiner dan 1, de items zijn vervangers van elkaar."
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+"Het aantal keren dat gevolgen en antecedenten samen worden weergegeven."
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Verkoop koppeling regels"
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr "Verkoop koppeling regels"
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr "Product koppel regel"
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr "Product koppel regel antecedent"
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr "Product koppel regel gevolg"
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr "Bereken verkoop product koppel regels"
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr "Koppel regel"
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr "Product aanbeveling koppel regel"
diff --git a/modules/sale_product_recommendation_association_rule/locale/pl.po b/modules/sale_product_recommendation_association_rule/locale/pl.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/pl.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/pt.po b/modules/sale_product_recommendation_association_rule/locale/pt.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/pt.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/ro.po b/modules/sale_product_recommendation_association_rule/locale/ro.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/ro.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/ru.po b/modules/sale_product_recommendation_association_rule/locale/ru.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/ru.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/sl.po b/modules/sale_product_recommendation_association_rule/locale/sl.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/sl.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/tr.po b/modules/sale_product_recommendation_association_rule/locale/tr.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/tr.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/uk.po b/modules/sale_product_recommendation_association_rule/locale/uk.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/uk.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/locale/zh_CN.po b/modules/sale_product_recommendation_association_rule/locale/zh_CN.po
new file mode 100644
index 0000000000..2f78b549e4
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/locale/zh_CN.po
@@ -0,0 +1,129 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.configuration,product_association_rule_max_length:"
+msgid "The maximal number of products for a rule."
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_confidence:"
+msgid "Minimum Confidence"
+msgstr ""
+
+msgctxt "field:sale.configuration,product_association_rule_min_support:"
+msgid "Minimum Support"
+msgstr ""
+
+msgctxt ""
+"field:sale.configuration,product_association_rule_transactions_up_to:"
+msgid "Transactions Up to"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedent_names:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,antecedents:"
+msgid "Antecedents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,confidence:"
+msgid "Confidence"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequent_names:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,consequents:"
+msgid "Consequents"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,conviction:"
+msgid "Conviction"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,lift:"
+msgid "Lift"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule,support:"
+msgid "Support"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.antecedent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,product:"
+msgid "Product"
+msgstr ""
+
+msgctxt "field:sale.product.association.rule.consequent,rule:"
+msgid "Rule"
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_confidence:"
+msgid "The minimum probability of the rule."
+msgstr ""
+
+msgctxt "help:sale.configuration,product_association_rule_min_support:"
+msgid ""
+"The minimum frequency of which the items in the rule appear together in the "
+"data set."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,confidence:"
+msgid "Probability of consequents, given antecedents."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,conviction:"
+msgid "The frequency that the rule makes an incorrect prediction."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,lift:"
+msgid ""
+"If equals to 1, the two occurrences are independent of each other.\n"
+"If greater than 1, the degree to which the two occurrences are dependent on one another.\n"
+"If less than 1, the items are substitute to each other."
+msgstr ""
+
+msgctxt "help:sale.product.association.rule,support:"
+msgid "The frequency of consequents and antecedents appear together."
+msgstr ""
+
+msgctxt "model:ir.action,name:act_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:ir.ui.menu,name:menu_product_association_rule_form"
+msgid "Sale Association Rules"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule,name:"
+msgid "Product Association Rule"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.antecedent,name:"
+msgid "Product Association Rule Antecedent"
+msgstr ""
+
+msgctxt "model:sale.product.association.rule.consequent,name:"
+msgid "Product Association Rule Consequent"
+msgstr ""
+
+msgctxt "selection:ir.cron,method:"
+msgid "Compute Sale Product Association Rules"
+msgstr ""
+
+msgctxt "selection:sale.configuration,product_recommendation_method:"
+msgid "Association Rule"
+msgstr ""
+
+msgctxt "view:sale.configuration:"
+msgid "Product Recommendation Association Rule"
+msgstr ""
diff --git a/modules/sale_product_recommendation_association_rule/sale.py b/modules/sale_product_recommendation_association_rule/sale.py
new file mode 100644
index 0000000000..b149d4537c
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/sale.py
@@ -0,0 +1,298 @@
+# 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 itertools import groupby
+
+from efficient_apriori import apriori
+
+from trytond.cache import Cache
+from trytond.model import Index, ModelSQL, ModelView, fields
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import TimeDelta
+from trytond.transaction import Transaction
+
+
+class Configuration(metaclass=PoolMeta):
+ __name__ = 'sale.configuration'
+
+ product_association_rule_transactions_up_to = fields.TimeDelta(
+ "Transactions Up to",
+ domain=['OR',
+ ('product_association_rule_transactions_up_to', '=', None),
+ ('product_association_rule_transactions_up_to', '>=', TimeDelta()),
+ ])
+ product_association_rule_min_support = fields.Float(
+ "Minimum Support", required=True,
+ domain=[
+ ('product_association_rule_min_support', '>=', 0),
+ ('product_association_rule_min_support', '<=', 1),
+ ],
+ help="The minimum frequency of which the items in the rule "
+ "appear together in the data set.")
+ product_association_rule_min_confidence = fields.Float(
+ "Minimum Confidence", required=True,
+ domain=[
+ ('product_association_rule_min_confidence', '>=', 0),
+ ('product_association_rule_min_confidence', '<=', 1),
+ ],
+ help="The minimum probability of the rule.")
+ product_association_rule_max_length = fields.Integer(
+ "The maximal number of products for a rule.", required=True,
+ domain=[
+ ('product_association_rule_max_length', '>', 0),
+ ])
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.product_recommendation_method.selection.append(
+ ('association_rule', "Association Rule"))
+
+ @classmethod
+ def default_product_association_rule_min_support(cls):
+ return 0.3
+
+ @classmethod
+ def default_product_association_rule_min_confidence(cls):
+ return 0.5
+
+ @classmethod
+ def default_product_association_rule_max_length(cls):
+ return 8
+
+
+class Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @fields.depends(methods=['_recommended_products_association_rule'])
+ def on_change_with_recommended_products(self, name=None):
+ return super().on_change_with_recommended_products(name=name)
+
+ @fields.depends('lines')
+ def _recommended_products_association_rule(self):
+ pool = Pool()
+ Rule = pool.get('sale.product.association.rule')
+ if self.lines:
+ products = [
+ l.product for l in self.lines
+ if getattr(l, 'product', None)]
+ yield from Rule.recommend(products)
+
+
+class ProductAssociationRule(ModelSQL, ModelView):
+ "Product Association Rule"
+ __name__ = 'sale.product.association.rule'
+
+ antecedents = fields.Many2Many(
+ 'sale.product.association.rule.antecedent', 'rule', 'product',
+ "Antecedents")
+ antecedent_names = fields.Function(fields.Char(
+ "Antecedents"), 'get_product_names')
+ consequents = fields.Many2Many(
+ 'sale.product.association.rule.consequent', 'rule', 'product',
+ "Consequents")
+ consequent_names = fields.Function(fields.Char(
+ "Consequents"), 'get_product_names')
+ confidence = fields.Float(
+ "Confidence",
+ domain=[
+ ('confidence', '>=', 0),
+ ('confidence', '<=', 1),
+ ],
+ help="Probability of consequents, given antecedents.")
+ support = fields.Float(
+ "Support",
+ domain=[
+ ('support', '>=', 0),
+ ('support', '<=', 1),
+ ],
+ help="The frequency of consequents and antecedents appear together.")
+ lift = fields.Float(
+ "Lift",
+ domain=[
+ ('lift', '>=', 0),
+ ],
+ help="If equals to 1, the two occurrences are "
+ "independent of each other.\n"
+ "If greater than 1, the degree to which the two occurrences are "
+ "dependent on one another.\n"
+ "If less than 1, the items are substitute to each other.")
+ conviction = fields.Float(
+ "Conviction",
+ domain=[
+ ('conviction', '>=', 0),
+ ],
+ help="The frequency that the rule makes an incorrect prediction.")
+ _find_rules_cache = Cache(__name__ + '._find_rules', context=False)
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_indexes.add(
+ Index(
+ t,
+ (t.lift, Index.Range(order='DESC')),
+ (t.conviction, Index.Range(order='ASC'))))
+
+ def get_product_names(self, name):
+ return ', '.join(
+ p.rec_name for p in getattr(self, name[:-len('_names')] + 's'))
+
+ @classmethod
+ def clean(cls, domain=None):
+ table = cls.__table__()
+ cursor = Transaction().connection.cursor()
+ if domain:
+ query = cls.search(domain, query=True)
+ where = table.id.in_(query)
+ else:
+ where = None
+ cursor.execute(*table.delete(where=where))
+
+ @classmethod
+ def transactions(cls):
+ "Yield transaction as sets of product ids"
+ yield from cls.transactions_sale()
+
+ @classmethod
+ def transactions_sale(cls, domain=None):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Sale = pool.get('sale.sale')
+ SaleLine = pool.get('sale.line')
+ Configuration = pool.get('sale.configuration')
+
+ config = Configuration(1)
+ today = Date.today()
+ date = today
+ if not config.product_association_rule_transactions_up_to:
+ return
+ date -= config.product_association_rule_transactions_up_to
+
+ lines = SaleLine.search([
+ ('sale.sale_date', '>=', date),
+ ('sale.state', 'not in', ['draft', 'cancelled']),
+ domain or [],
+ ],
+ order=[('sale.id', 'DESC')])
+ for sale, lines in groupby(lines, lambda l: l.sale):
+ yield {
+ l.product.id for l in lines
+ if l.product and Sale._is_recommendable_product(l.product)}
+
+ @classmethod
+ def compute(cls):
+ pool = Pool()
+ Configuration = pool.get('sale.configuration')
+
+ config = Configuration(1)
+ cls.clean()
+ cls._find_rules_cache.clear()
+ transactions = cls.transactions()
+
+ _, rules = apriori(
+ transactions,
+ min_support=config.product_association_rule_min_support,
+ min_confidence=config.product_association_rule_min_confidence,
+ max_length=config.product_association_rule_max_length)
+
+ cls.save([cls.from_rule(rule) for rule in rules])
+
+ @classmethod
+ def from_rule(cls, rule):
+ return cls(
+ antecedents=rule.lhs,
+ consequents=rule.rhs,
+ confidence=rule.confidence,
+ support=rule.support,
+ lift=rule.lift,
+ conviction=rule.conviction)
+
+ @classmethod
+ def _find_rules(cls, products, domain, lift='DESC'):
+ product_ids = {p.id for p in products}
+ key = (sorted(product_ids), domain, lift)
+ rules = cls._find_rules_cache.get(key)
+ if rules is not None:
+ rules = cls.browse(rules)
+ else:
+ rules = cls.search([
+ ('antecedents', 'in', list(product_ids)),
+ domain,
+ ],
+ order=[('lift', lift), ('conviction', 'ASC')])
+ rules = [
+ r for r in rules
+ if set(map(int, r.antecedents)) <= product_ids]
+ cls._find_rules_cache.set(key, [r.id for r in rules])
+
+ products = set(products)
+ for rule in rules:
+ yield from (set(rule.consequents) - products)
+ products.update(rule.consequents)
+
+ @classmethod
+ def recommend(cls, products):
+ return cls._find_rules(products, [('lift', '>', 1)], lift='DESC')
+
+ @classmethod
+ def substitute(cls, products):
+ return cls._find_rules(products, [('lift', '<', 1)], lift='DESC')
+
+
+class ProductAssociationRuleAntecedent(ModelSQL):
+ "Product Association Rule Antecedent"
+ __name__ = 'sale.product.association.rule.antecedent'
+
+ rule = fields.Many2One(
+ 'sale.product.association.rule', "Rule",
+ required=True, ondelete='CASCADE')
+ product = fields.Many2One(
+ 'product.product', "Product", required=True, ondelete='CASCADE')
+
+
+class ProductAssociationRuleConsequent(ModelSQL):
+ "Product Association Rule Consequent"
+ __name__ = 'sale.product.association.rule.consequent'
+
+ rule = fields.Many2One(
+ 'sale.product.association.rule', "Rule",
+ required=True, ondelete='CASCADE')
+ product = fields.Many2One(
+ 'product.product', "Product", required=True, ondelete='CASCADE')
+
+
+class ProductAssociationRulePOS(metaclass=PoolMeta):
+ __name__ = 'sale.product.association.rule'
+
+ @classmethod
+ def transactions(cls):
+ yield from super().transactions()
+ yield from cls.transactions_pos()
+
+ @classmethod
+ def transactions_pos(cls, domain=None):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Sale = pool.get('sale.point.sale')
+ SaleLine = pool.get('sale.point.sale.line')
+ Configuration = pool.get('sale.configuration')
+
+ config = Configuration(1)
+ today = Date.today()
+ date = today
+ if not config.product_association_rule_transactions_up_to:
+ return
+ date -= config.product_association_rule_transactions_up_to
+
+ lines = SaleLine.search([
+ ('sale.date', '>=', date),
+ ('sale.state', 'not in', ['open', 'cancelled']),
+ domain or [],
+ ],
+ order=[('sale.id', 'DESC')])
+ for sale, lines in groupby(lines, lambda l: l.sale):
+ yield {
+ l.product.id for l in lines
+ if l.product and Sale._is_recommendable_product(l.product)}
diff --git a/modules/sale_product_recommendation_association_rule/sale.xml b/modules/sale_product_recommendation_association_rule/sale.xml
new file mode 100644
index 0000000000..05c0fbc527
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/sale.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+ sale.configuration
+
+ configuration_form
+
+
+
+ sale.product.association.rule
+ tree
+ product_association_rule_list
+
+
+
+ sale.product.association.rule
+ form
+ product_association_rule_form
+
+
+
+ Sale Association Rules
+ sale.product.association.rule
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sale.product.association.rule|compute
+
+ weeks
+
+
+
diff --git a/modules/sale_product_recommendation_association_rule/setup.py b/modules/sale_product_recommendation_association_rule/setup.py
new file mode 100755
index 0000000000..7a2f67f0c6
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/setup.py
@@ -0,0 +1,166 @@
+#!/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 find_packages, setup
+
+
+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_product_recommendation_association_rule'
+
+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 = ['efficient-apriori']
+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_point'),
+ ]
+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 learn association rule for recommendation',
+ 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-product-recommendation-association-rule'),
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": (
+ 'https://hg.tryton.org/modules/'
+ 'sale_product_recommendation_association_rule'),
+ },
+ keywords='tryton sale product recommendation association rule learning',
+ package_dir={
+ 'trytond.modules.sale_product_recommendation_association_rule': '.',
+ },
+ packages=(
+ ['trytond.modules.sale_product_recommendation_association_rule']
+ + ['trytond.modules.'
+ 'sale_product_recommendation_association_rule.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.'
+ 'sale_product_recommendation_association_rule': (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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_product_recommendation_association_rule = trytond.modules.sale_product_recommendation_association_rule
+ """, # noqa: E501
+ )
diff --git a/modules/sale_product_recommendation_association_rule/tests/__init__.py b/modules/sale_product_recommendation_association_rule/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_product_recommendation_association_rule/tests/scenario_sale_product_recommendation_association_rule.rst b/modules/sale_product_recommendation_association_rule/tests/scenario_sale_product_recommendation_association_rule.rst
new file mode 100644
index 0000000000..4dbc947b48
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/tests/scenario_sale_product_recommendation_association_rule.rst
@@ -0,0 +1,161 @@
+=====================================================
+Sale Product Recommendation Association Rule 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)
+
+Activate modules::
+
+ >>> config = activate_modules('sale_product_recommendation_association_rule')
+
+ >>> Cron = Model.get('ir.cron')
+ >>> Party = Model.get('party.party')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductAssociationRule = Model.get('sale.product.association.rule')
+ >>> Sale = Model.get('sale.sale')
+ >>> SaleConfiguration = Model.get('sale.configuration')
+ >>> Uom = Model.get('product.uom')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Configuration association rule::
+
+ >>> sale_config = SaleConfiguration(1)
+ >>> sale_config.product_association_rule_transactions_up_to = (
+ ... dt.timedelta(days=30))
+ >>> sale_config.product_recommendation_method = 'association_rule'
+ >>> sale_config.save()
+
+Create customer::
+
+ >>> customer = Party(name="Customer")
+ >>> customer.save()
+
+Create products::
+
+ >>> unit, = Uom.find([('name', '=', "Unit")])
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Egg"
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.recommendable = True
+ >>> template.list_price = Decimal('1')
+ >>> template.save()
+ >>> egg, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Bacon"
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.recommendable = True
+ >>> template.list_price = Decimal('5')
+ >>> template.save()
+ >>> bacon, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Soup"
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.recommendable = True
+ >>> template.list_price = Decimal('8')
+ >>> template.save()
+ >>> soup, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Apple"
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.recommendable = True
+ >>> template.list_price = Decimal('3')
+ >>> template.save()
+ >>> apple, = template.products
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Banana"
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.recommendable = True
+ >>> template.list_price = Decimal('4')
+ >>> template.save()
+ >>> banana, = template.products
+
+Create some sales::
+
+ >>> sale = Sale(party=customer)
+ >>> line = sale.lines.new(product=egg)
+ >>> line.quantity = 12
+ >>> line = sale.lines.new(product=bacon)
+ >>> line.quantity = 2
+ >>> line = sale.lines.new(product=soup)
+ >>> line.quantity = 1
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.state
+ 'confirmed'
+
+ >>> sale = Sale(party=customer)
+ >>> line = sale.lines.new(product=egg)
+ >>> line.quantity = 6
+ >>> line = sale.lines.new(product=bacon)
+ >>> line.quantity = 4
+ >>> line = sale.lines.new(product=apple)
+ >>> line.quantity = 5
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+
+ >>> sale = Sale(party=customer)
+ >>> line = sale.lines.new(product=soup)
+ >>> line.quantity = 3
+ >>> line = sale.lines.new(product=bacon)
+ >>> line.quantity = 2
+ >>> line = sale.lines.new(product=banana)
+ >>> line.quantity = 5
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+
+ >>> sale = Sale(party=customer)
+ >>> line = sale.lines.new(product=apple)
+ >>> line.quantity = 2
+ >>> line = sale.lines.new(product=banana)
+ >>> line.quantity = 2
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+
+Compute association rules::
+
+ >>> cron_compute_association_rule, = Cron.find([
+ ... ('method', '=', 'sale.product.association.rule|compute'),
+ ... ])
+ >>> cron_compute_association_rule.click('run_once')
+
+ >>> bool(ProductAssociationRule.find([]))
+ True
+
+Test recommended products::
+
+ >>> sale = Sale(party=customer)
+ >>> [p.name for p in sale.recommended_products]
+ []
+ >>> line = sale.lines.new(product=apple)
+ >>> [p.name for p in sale.recommended_products]
+ []
+ >>> line = sale.lines.new(product=egg)
+ >>> [p.name for p in sale.recommended_products]
+ ['Bacon']
diff --git a/modules/sale_product_recommendation_association_rule/tests/test_module.py b/modules/sale_product_recommendation_association_rule/tests/test_module.py
new file mode 100644
index 0000000000..9198036f25
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SaleProductRecommendationAssociationRuleTestCase(ModuleTestCase):
+ "Test Sale Product Recommendation Association Rule module"
+ module = 'sale_product_recommendation_association_rule'
+ extras = ['sale_point']
+
+
+del ModuleTestCase
diff --git a/modules/sale_product_recommendation_association_rule/tests/test_scenario.py b/modules/sale_product_recommendation_association_rule/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_product_recommendation_association_rule/tox.ini b/modules/sale_product_recommendation_association_rule/tox.ini
new file mode 100644
index 0000000000..2672a37250
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_product_recommendation_association_rule/* -m unittest discover -s tests
+ coverage report --include=./**/sale_product_recommendation_association_rule/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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_recommendation_association_rule/tryton.cfg b/modules/sale_product_recommendation_association_rule/tryton.cfg
new file mode 100644
index 0000000000..9ce730b22b
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/tryton.cfg
@@ -0,0 +1,11 @@
+[tryton]
+version=6.7.0
+depends:
+ ir
+ product
+ sale
+ sale_product_recommendation
+extras_depend:
+ sale_point
+xml:
+ sale.xml
diff --git a/modules/sale_product_recommendation_association_rule/view/configuration_form.xml b/modules/sale_product_recommendation_association_rule/view/configuration_form.xml
new file mode 100644
index 0000000000..4cd1912290
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/view/configuration_form.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_product_recommendation_association_rule/view/product_association_rule_form.xml b/modules/sale_product_recommendation_association_rule/view/product_association_rule_form.xml
new file mode 100644
index 0000000000..6bbd95537b
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/view/product_association_rule_form.xml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/modules/sale_product_recommendation_association_rule/view/product_association_rule_list.xml b/modules/sale_product_recommendation_association_rule/view/product_association_rule_list.xml
new file mode 100644
index 0000000000..cec19f9a07
--- /dev/null
+++ b/modules/sale_product_recommendation_association_rule/view/product_association_rule_list.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/sale_promotion/.drone.yml b/modules/sale_promotion/.drone.yml
new file mode 100644
index 0000000000..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_promotion/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_promotion/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_promotion/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_promotion/CHANGELOG b/modules/sale_promotion/CHANGELOG
new file mode 100644
index 0000000000..3c5d4df37b
--- /dev/null
+++ b/modules/sale_promotion/CHANGELOG
@@ -0,0 +1,56 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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..b97a61c3dd
--- /dev/null
+++ b/modules/sale_promotion/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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_promotion/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..345ee7479b
--- /dev/null
+++ b/modules/sale_promotion/__init__.py
@@ -0,0 +1,16 @@
+# 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..ae402549e2
--- /dev/null
+++ b/modules/sale_promotion/locale/bg.po
@@ -0,0 +1,136 @@
+#
+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,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 "Единица"
+
+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..b4bf841309
--- /dev/null
+++ b/modules/sale_promotion/locale/ca.po
@@ -0,0 +1,123 @@
+#
+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,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,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..c7b921819d
--- /dev/null
+++ b/modules/sale_promotion/locale/cs.po
@@ -0,0 +1,124 @@
+#
+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,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,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..a3515fcc0e
--- /dev/null
+++ b/modules/sale_promotion/locale/de.po
@@ -0,0 +1,123 @@
+#
+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,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,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..c6915ba0e2
--- /dev/null
+++ b/modules/sale_promotion/locale/es.po
@@ -0,0 +1,123 @@
+#
+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,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,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..196c20836d
--- /dev/null
+++ b/modules/sale_promotion/locale/es_419.po
@@ -0,0 +1,124 @@
+#
+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,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,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..bd7cf46e6c
--- /dev/null
+++ b/modules/sale_promotion/locale/et.po
@@ -0,0 +1,120 @@
+#
+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 ""
+
+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,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..d076041dd4
--- /dev/null
+++ b/modules/sale_promotion/locale/fa.po
@@ -0,0 +1,121 @@
+#
+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 ""
+
+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,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..4d0df617ca
--- /dev/null
+++ b/modules/sale_promotion/locale/fi.po
@@ -0,0 +1,123 @@
+#
+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,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,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..4a638d00bd
--- /dev/null
+++ b/modules/sale_promotion/locale/fr.po
@@ -0,0 +1,123 @@
+#
+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,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,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..588ce81b5e
--- /dev/null
+++ b/modules/sale_promotion/locale/hu.po
@@ -0,0 +1,134 @@
+#
+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 ""
+
+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"
+
+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..a33661f29d
--- /dev/null
+++ b/modules/sale_promotion/locale/id.po
@@ -0,0 +1,120 @@
+#
+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,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,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..305cdd6a93
--- /dev/null
+++ b/modules/sale_promotion/locale/it.po
@@ -0,0 +1,123 @@
+#
+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 "Importo"
+
+msgctxt "field:sale.promotion,categories:"
+msgid "Categories"
+msgstr "Categorie"
+
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Azienda"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+msgstr "Valuta"
+
+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,untaxed_amount:"
+msgid "Untaxed Amount"
+msgstr "Importo non tassato"
+
+msgctxt "field:sale.promotion-product.category,category:"
+msgid "Category"
+msgstr "Categoria"
+
+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"
+
+msgctxt "model:ir.action,name:act_promotion_form"
+msgid "Promotions"
+msgstr "Promozioni"
+
+msgctxt "model:ir.action,name:act_promotion_relate"
+msgid "Sale Promotions"
+msgstr "Promozione su vendite"
+
+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 per la promozione \"%(promotion)s\" con "
+"eccezione \"%(exception)s\"."
+
+msgctxt "model:ir.rule.group,name:rule_group_promotion_companies"
+msgid "User in companies"
+msgstr "Utente in aziende"
+
+msgctxt "model:ir.ui.menu,name:menu_promotion"
+msgid "Promotions"
+msgstr "Promozioni"
+
+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 "Promozione vendita - Categoria di prodotto"
+
+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..278cea9dd6
--- /dev/null
+++ b/modules/sale_promotion/locale/lo.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 ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "ຫ້ອງການ/ສຳນັກງານ"
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+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 "ໜ່ວຍ"
+
+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..3ae6b0e5ba
--- /dev/null
+++ b/modules/sale_promotion/locale/lt.po
@@ -0,0 +1,124 @@
+#
+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,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,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..a4f43c7011
--- /dev/null
+++ b/modules/sale_promotion/locale/nl.po
@@ -0,0 +1,123 @@
+#
+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,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,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\"."
+
+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..0b46ce026d
--- /dev/null
+++ b/modules/sale_promotion/locale/pl.po
@@ -0,0 +1,123 @@
+#
+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 ""
+
+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,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..4a1550e7f9
--- /dev/null
+++ b/modules/sale_promotion/locale/pt.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 "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 ""
+
+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,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..dff5e66198
--- /dev/null
+++ b/modules/sale_promotion/locale/ro.po
@@ -0,0 +1,119 @@
+#
+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,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,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..63b58cb56e
--- /dev/null
+++ b/modules/sale_promotion/locale/ru.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 ""
+
+#, fuzzy
+msgctxt "field:sale.promotion,company:"
+msgid "Company"
+msgstr "Учет.орг."
+
+msgctxt "field:sale.promotion,currency:"
+msgid "Currency"
+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 "Штука"
+
+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..78aa88b883
--- /dev/null
+++ b/modules/sale_promotion/locale/sl.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 "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 ""
+
+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,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..4d0df617ca
--- /dev/null
+++ b/modules/sale_promotion/locale/tr.po
@@ -0,0 +1,123 @@
+#
+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,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,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/uk.po b/modules/sale_promotion/locale/uk.po
new file mode 100644
index 0000000000..990ce77c55
--- /dev/null
+++ b/modules/sale_promotion/locale/uk.po
@@ -0,0 +1,119 @@
+#
+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 ""
+
+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,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 ""
+
+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/zh_CN.po b/modules/sale_promotion/locale/zh_CN.po
new file mode 100644
index 0000000000..9bb02b671a
--- /dev/null
+++ b/modules/sale_promotion/locale/zh_CN.po
@@ -0,0 +1,124 @@
+#
+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,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,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..8b6c12e8f6
--- /dev/null
+++ b/modules/sale_promotion/sale.py
@@ -0,0 +1,335 @@
+# 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.model import (
+ DeactivableMixin, MatchMixin, ModelSQL, ModelView, Workflow, fields)
+from trytond.modules.currency.fields import Monetary
+from trytond.modules.product import price_digits, round_price
+from trytond.modules.product_price_list import Null
+from trytond.pool import Pool, PoolMeta
+from trytond.pyson import Bool, Eval, If
+from trytond.tools import decistmt
+from trytond.transaction import Transaction
+
+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)),
+ ],
+ depends={'sale'})
+
+
+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,
+ 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),
+ ])
+ 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),
+ ])
+ price_list = fields.Many2One('product.price_list', 'Price List',
+ ondelete='CASCADE',
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ])
+
+ amount = Monetary("Amount", currency='currency', digits='currency')
+ currency = fields.Many2One(
+ 'currency.currency', "Currency",
+ states={
+ 'required': Bool(Eval('amount', 0)),
+ })
+ untaxed_amount = fields.Boolean(
+ "Untaxed Amount",
+ states={
+ 'invisible': ~Eval('amount'),
+ })
+
+ quantity = fields.Float('Quantity', digits='unit')
+ unit = fields.Many2One('product.uom', 'Unit',
+ states={
+ 'required': Bool(Eval('quantity', 0)),
+ })
+ 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
+
+ @classmethod
+ def validate_fields(cls, promotions, field_names):
+ super().validate_fields(promotions, field_names)
+ cls.check_formula(promotions, field_names)
+
+ @classmethod
+ def check_formula(cls, promotions, field_names=None):
+ if field_names and 'formula' not in field_names:
+ return
+ for promotion in promotions:
+ context = promotion.get_context_formula(None)
+ try:
+ unit_price = promotion.get_unit_price(**context)
+ if not isinstance(unit_price, Decimal):
+ raise ValueError('Not a Decimal')
+ except Exception as exception:
+ raise FormulaError(
+ gettext('sale_promotion.msg_invalid_formula',
+ formula=promotion.formula,
+ promotion=promotion.rec_name,
+ exception=exception)) from exception
+
+ @classmethod
+ def _promotions_domain(cls, sale):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ with Transaction().set_context(company=sale.company.id):
+ 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 is not None:
+ 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 if unit_price is not None else Null(),
+ },
+ }
+
+ 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')
+ 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')
+ 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..d312bf411c
--- /dev/null
+++ b/modules/sale_promotion/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ 'Topic :: Office/Business :: Financial :: Accounting',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_promotion = trytond.modules.sale_promotion
+ """,
+ )
diff --git a/modules/sale_promotion/tests/__init__.py b/modules/sale_promotion/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_promotion/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_promotion/tests/test_module.py
new file mode 100644
index 0000000000..1162df0d31
--- /dev/null
+++ b/modules/sale_promotion/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SalePromotionTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Promotion module'
+ module = 'sale_promotion'
+
+
+del ModuleTestCase
diff --git a/modules/sale_promotion/tests/test_scenario.py b/modules/sale_promotion/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_promotion/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_promotion/tox.ini b/modules/sale_promotion/tox.ini
new file mode 100644
index 0000000000..50388260e7
--- /dev/null
+++ b/modules/sale_promotion/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_promotion/* -m unittest discover -s tests
+ coverage report --include=./**/sale_promotion/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..773fe2500f
--- /dev/null
+++ b/modules/sale_promotion/tryton.cfg
@@ -0,0 +1,14 @@
+[tryton]
+version=6.7.0
+depends:
+ company
+ currency
+ 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..a10bb20a6a
--- /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..70549c391b
--- /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..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_promotion_coupon/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_promotion_coupon/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_promotion_coupon/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_promotion_coupon/CHANGELOG b/modules/sale_promotion_coupon/CHANGELOG
new file mode 100644
index 0000000000..a2b0813d6f
--- /dev/null
+++ b/modules/sale_promotion_coupon/CHANGELOG
@@ -0,0 +1,35 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+* Support many parties to count coupon
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..3e3fc46e16
--- /dev/null
+++ b/modules/sale_promotion_coupon/COPYRIGHT
@@ -0,0 +1,14 @@
+Copyright (C) 2017-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_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..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_promotion_coupon/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft 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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/bg.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..778048d84e
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/ca.po
@@ -0,0 +1,83 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Tercers dels cupons"
+
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/cs.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..5eedf76036
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/de.po
@@ -0,0 +1,85 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Coupons Parteien"
+
+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..433204151d
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/es.po
@@ -0,0 +1,83 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Terceros de los cupones"
+
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/es_419.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..308a34abb2
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/et.po
@@ -0,0 +1,82 @@
+#
+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"
+
+#, fuzzy
+msgctxt "field:sale.sale,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Kupongid"
+
+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..7bec5737fe
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/fa.po
@@ -0,0 +1,84 @@
+#
+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 "شماره"
+
+#, fuzzy
+msgctxt "field:sale.sale,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/fi.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..63643f5f37
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/fr.po
@@ -0,0 +1,83 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Tiers de coupon"
+
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/hu.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..85269b46e1
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/id.po
@@ -0,0 +1,84 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "field:sale.promotion,coupons:"
+msgid "Coupons"
+msgstr "Kupon"
+
+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"
+
+#, fuzzy
+msgctxt "field:sale.sale,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Kupon"
+
+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..2331f98df0
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/it.po
@@ -0,0 +1,81 @@
+#
+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 "Attivo"
+
+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,coupon_parties:"
+msgid "Coupon Parties"
+msgstr ""
+
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/lo.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..a86be04e41
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/lt.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..4f3361c49e
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/nl.po
@@ -0,0 +1,83 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+msgstr "Relatie Bon"
+
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/pl.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/pt.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/ro.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/ru.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/sl.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/tr.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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/uk.po b/modules/sale_promotion_coupon/locale/uk.po
new file mode 100644
index 0000000000..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/uk.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..eb92c14403
--- /dev/null
+++ b/modules/sale_promotion_coupon/locale/zh_CN.po
@@ -0,0 +1,81 @@
+#
+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,coupon_parties:"
+msgid "Coupon Parties"
+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..fa88b57528
--- /dev/null
+++ b/modules/sale_promotion_coupon/sale.py
@@ -0,0 +1,230 @@
+# 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 (
+ DeactivableMixin, ModelSQL, ModelView, Workflow, fields)
+from trytond.pool import Pool, PoolMeta
+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", 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')
+ if isinstance(party, int):
+ party = [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.in_(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_fields(cls, numbers, field_names):
+ super().validate_fields(numbers, field_names)
+ cls.check_unique(numbers, field_names)
+
+ @classmethod
+ def check_unique(cls, numbers, field_names=None):
+ if field_names and not (field_names & {'number', 'coupon'}):
+ return
+ 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('coupon_parties', []),
+ },
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends={'coupon_parties'})
+ coupon_parties = fields.Function(fields.Many2Many(
+ 'party.party', None, None, "Coupon Parties",
+ context={
+ 'company': Eval('company', -1),
+ }),
+ 'on_change_with_coupon_parties')
+
+ @fields.depends(methods=['_coupon_parties'])
+ def on_change_with_coupon_parties(self, name=None):
+ return [p.id for p in self._coupon_parties()]
+
+ @fields.depends('party')
+ def _coupon_parties(self):
+ parties = set()
+ if self.party:
+ parties.add(self.party)
+ return parties
+
+ @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, 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..687337f6c6
--- /dev/null
+++ b/modules/sale_promotion_coupon/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 find_packages, setup
+
+
+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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_promotion_coupon = trytond.modules.sale_promotion_coupon
+ """,
+ )
diff --git a/modules/sale_promotion_coupon/tests/__init__.py b/modules/sale_promotion_coupon/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_promotion_coupon/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
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_module.py b/modules/sale_promotion_coupon/tests/test_module.py
new file mode 100644
index 0000000000..dabaec3235
--- /dev/null
+++ b/modules/sale_promotion_coupon/tests/test_module.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.modules.company.tests import CompanyTestMixin
+from trytond.tests.test_tryton import ModuleTestCase
+
+
+class SalePromotionCouponTestCase(CompanyTestMixin, ModuleTestCase):
+ 'Test Sale Promotion Coupon module'
+ module = 'sale_promotion_coupon'
+
+
+del ModuleTestCase
diff --git a/modules/sale_promotion_coupon/tests/test_scenario.py b/modules/sale_promotion_coupon/tests/test_scenario.py
new file mode 100644
index 0000000000..dc1d23e7e5
--- /dev/null
+++ b/modules/sale_promotion_coupon/tests/test_scenario.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.tests.test_tryton import load_doc_tests
+
+
+def load_tests(*args, **kwargs):
+ return load_doc_tests(__name__, __file__, *args, **kwargs)
diff --git a/modules/sale_promotion_coupon/tox.ini b/modules/sale_promotion_coupon/tox.ini
new file mode 100644
index 0000000000..9dd456ff6a
--- /dev/null
+++ b/modules/sale_promotion_coupon/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_promotion_coupon/* -m unittest discover -s tests
+ coverage report --include=./**/sale_promotion_coupon/* --omit=*/tests/*
+deps =
+ coverage
+ postgresql: psycopg2 >= 2.7.0
+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..363c94c2d3
--- /dev/null
+++ b/modules/sale_promotion_coupon/tryton.cfg
@@ -0,0 +1,10 @@
+[tryton]
+version=6.7.0
+depends:
+ company
+ 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_promotion_coupon_payment/.drone.yml b/modules/sale_promotion_coupon_payment/.drone.yml
new file mode 100644
index 0000000000..b45ef267ef
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/.drone.yml
@@ -0,0 +1,78 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+ check_doc:
+ image: ${IMAGE}
+ commands:
+ - pip install sphinx
+ - python -m sphinx -T -E -W -n -b html doc _build/html
+ - python -m sphinx -T -E -W -n -b linkcheck doc _build
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: postgresql
diff --git a/modules/sale_promotion_coupon_payment/.flake8 b/modules/sale_promotion_coupon_payment/.flake8
new file mode 100644
index 0000000000..fa6b4f66d1
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,E741,W503
diff --git a/modules/sale_promotion_coupon_payment/.isort.cfg b/modules/sale_promotion_coupon_payment/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_promotion_coupon_payment/CHANGELOG b/modules/sale_promotion_coupon_payment/CHANGELOG
new file mode 100644
index 0000000000..7762ad3c72
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/CHANGELOG
@@ -0,0 +1,3 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+Initial release
diff --git a/modules/sale_promotion_coupon_payment/COPYRIGHT b/modules/sale_promotion_coupon_payment/COPYRIGHT
new file mode 100644
index 0000000000..f8f170606e
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2022 B2CK
+Copyright (C) 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_promotion_coupon_payment/LICENSE b/modules/sale_promotion_coupon_payment/LICENSE
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/modules/sale_promotion_coupon_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_promotion_coupon_payment/MANIFEST.in b/modules/sale_promotion_coupon_payment/MANIFEST.in
new file mode 100644
index 0000000000..f7e7aaa36b
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGELOG
+include COPYRIGHT
+include LICENSE
+include README.rst
+include icons/LICENSE
+graft doc
diff --git a/modules/sale_promotion_coupon_payment/README.rst b/modules/sale_promotion_coupon_payment/README.rst
new file mode 120000
index 0000000000..176d9c2695
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/README.rst
@@ -0,0 +1 @@
+doc/index.rst
\ No newline at end of file
diff --git a/modules/sale_promotion_coupon_payment/__init__.py b/modules/sale_promotion_coupon_payment/__init__.py
new file mode 100644
index 0000000000..a341efebcf
--- /dev/null
+++ b/modules/sale_promotion_coupon_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 sale
+
+__all__ = ['register']
+
+
+def register():
+ Pool.register(
+ sale.Sale,
+ module='sale_promotion_coupon_payment', type_='model')
diff --git a/modules/sale_promotion_coupon_payment/doc/conf.py b/modules/sale_promotion_coupon_payment/doc/conf.py
new file mode 100644
index 0000000000..8513b72dd2
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/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_promotion_coupon_payment/doc/index.rst b/modules/sale_promotion_coupon_payment/doc/index.rst
new file mode 100644
index 0000000000..c0989f5d20
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/doc/index.rst
@@ -0,0 +1,11 @@
+####################################
+Sale Promotion Coupon Payment Module
+####################################
+
+The *Sale Promotion Coupon Payment Module* includes the identical parties from
+the payments to count usage per party.
+
+.. toctree::
+ :maxdepth: 2
+
+ releases
diff --git a/modules/sale_promotion_coupon_payment/doc/releases.rst b/modules/sale_promotion_coupon_payment/doc/releases.rst
new file mode 100644
index 0000000000..21b13c4745
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/doc/releases.rst
@@ -0,0 +1,7 @@
+.. _releases-index:
+
+=============
+Release notes
+=============
+
+.. include:: ../CHANGELOG
diff --git a/modules/sale_promotion_coupon_payment/locale/bg.po b/modules/sale_promotion_coupon_payment/locale/bg.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/bg.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/ca.po b/modules/sale_promotion_coupon_payment/locale/ca.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/ca.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/cs.po b/modules/sale_promotion_coupon_payment/locale/cs.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/cs.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/de.po b/modules/sale_promotion_coupon_payment/locale/de.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/de.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/es.po b/modules/sale_promotion_coupon_payment/locale/es.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/es.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/es_419.po b/modules/sale_promotion_coupon_payment/locale/es_419.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/es_419.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/et.po b/modules/sale_promotion_coupon_payment/locale/et.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/et.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/fa.po b/modules/sale_promotion_coupon_payment/locale/fa.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/fa.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/fi.po b/modules/sale_promotion_coupon_payment/locale/fi.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/fi.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/fr.po b/modules/sale_promotion_coupon_payment/locale/fr.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/fr.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/hu.po b/modules/sale_promotion_coupon_payment/locale/hu.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/hu.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/id.po b/modules/sale_promotion_coupon_payment/locale/id.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/id.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/it.po b/modules/sale_promotion_coupon_payment/locale/it.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/it.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/lo.po b/modules/sale_promotion_coupon_payment/locale/lo.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/lo.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/lt.po b/modules/sale_promotion_coupon_payment/locale/lt.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/lt.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/nl.po b/modules/sale_promotion_coupon_payment/locale/nl.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/nl.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/pl.po b/modules/sale_promotion_coupon_payment/locale/pl.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/pl.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/pt.po b/modules/sale_promotion_coupon_payment/locale/pt.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/pt.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/ro.po b/modules/sale_promotion_coupon_payment/locale/ro.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/ro.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/ru.po b/modules/sale_promotion_coupon_payment/locale/ru.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/ru.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/sl.po b/modules/sale_promotion_coupon_payment/locale/sl.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/sl.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/tr.po b/modules/sale_promotion_coupon_payment/locale/tr.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/tr.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/uk.po b/modules/sale_promotion_coupon_payment/locale/uk.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/uk.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/locale/zh_CN.po b/modules/sale_promotion_coupon_payment/locale/zh_CN.po
new file mode 100644
index 0000000000..c74b319ddb
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/locale/zh_CN.po
@@ -0,0 +1,3 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
diff --git a/modules/sale_promotion_coupon_payment/sale.py b/modules/sale_promotion_coupon_payment/sale.py
new file mode 100644
index 0000000000..cf38d2770d
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/sale.py
@@ -0,0 +1,16 @@
+# 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 Sale(metaclass=PoolMeta):
+ __name__ = 'sale.sale'
+
+ @fields.depends('party')
+ def _coupon_parties(self):
+ parties = super()._coupon_parties()
+ if self.party:
+ parties.update(self.party.payment_identical_parties)
+ return parties
diff --git a/modules/sale_promotion_coupon_payment/setup.py b/modules/sale_promotion_coupon_payment/setup.py
new file mode 100755
index 0000000000..7c0b37c744
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/setup.py
@@ -0,0 +1,159 @@
+#!/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 find_packages, setup
+
+
+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_promotion_coupon_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 = []
+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 = []
+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 link payment with 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/projects/'
+ 'modules-sale-promotion-coupon-payment'),
+ "Forum": 'https://www.tryton.org/forum',
+ "Source Code": (
+ 'https://hg.tryton.org/modules/sale_promotion_coupon_payment'),
+ },
+ keywords='tryton sale promotion coupon payment',
+ package_dir={'trytond.modules.sale_promotion_coupon_payment': '.'},
+ packages=(
+ ['trytond.modules.sale_promotion_coupon_payment']
+ + ['trytond.modules.sale_promotion_coupon_payment.%s' % p
+ for p in find_packages()]
+ ),
+ package_data={
+ 'trytond.modules.sale_promotion_coupon_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',
+ 'Natural Language :: Ukrainian',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Office/Business',
+ ],
+ license='GPL-3',
+ python_requires='>=3.7',
+ install_requires=requires,
+ extras_require={
+ 'test': tests_require,
+ },
+ dependency_links=dependency_links,
+ zip_safe=False,
+ entry_points="""
+ [trytond.modules]
+ sale_promotion_coupon_payment = trytond.modules.sale_promotion_coupon_payment
+ """, # noqa: E501
+ )
diff --git a/modules/sale_promotion_coupon_payment/tests/__init__.py b/modules/sale_promotion_coupon_payment/tests/__init__.py
new file mode 100644
index 0000000000..4effdfa4a2
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/tests/__init__.py
@@ -0,0 +1,2 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
diff --git a/modules/sale_promotion_coupon_payment/tests/test_module.py b/modules/sale_promotion_coupon_payment/tests/test_module.py
new file mode 100644
index 0000000000..ef44c41e04
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/tests/test_module.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.tests.test_tryton import ModuleTestCase
+
+
+class SalePromotionCouponPaymentTestCase(ModuleTestCase):
+ "Test Sale Promotion Coupon Payment module"
+ module = 'sale_promotion_coupon_payment'
+
+
+del ModuleTestCase
diff --git a/modules/sale_promotion_coupon_payment/tox.ini b/modules/sale_promotion_coupon_payment/tox.ini
new file mode 100644
index 0000000000..1c3823f653
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/tox.ini
@@ -0,0 +1,18 @@
+[tox]
+envlist = {py37,py38,py39,py310}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
+
+[testenv]
+extras = test
+commands =
+ coverage run --include=./**/sale_promotion_coupon_payment/* -m unittest discover -s tests
+ coverage report --include=./**/sale_promotion_coupon_payment/* --omit=*/tests/*
+deps =
+ coverage
+ {py37,py38,py39,py310}-postgresql: psycopg2 >= 2.5
+ pypy3-postgresql: psycopg2cffi >= 2.5
+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_payment/tryton.cfg b/modules/sale_promotion_coupon_payment/tryton.cfg
new file mode 100644
index 0000000000..8e3cff602e
--- /dev/null
+++ b/modules/sale_promotion_coupon_payment/tryton.cfg
@@ -0,0 +1,7 @@
+[tryton]
+version=6.7.0
+depends:
+ account_payment
+ ir
+ sale_promotion_coupon
+xml:
diff --git a/modules/sale_secondary_unit/.drone.yml b/modules/sale_secondary_unit/.drone.yml
new file mode 100644
index 0000000000..cb4fbecb4d
--- /dev/null
+++ b/modules/sale_secondary_unit/.drone.yml
@@ -0,0 +1,70 @@
+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/*
+ volumes:
+ - cache:/root/.cache
+
+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.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
+ - IMAGE: python:3.10
+ TOXENV: py310
+ DATABASE: sqlite
+ - IMAGE: python:3.10
+ TOXENV: py310
+ 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/.isort.cfg b/modules/sale_secondary_unit/.isort.cfg
new file mode 100644
index 0000000000..e1c6495da9
--- /dev/null
+++ b/modules/sale_secondary_unit/.isort.cfg
@@ -0,0 +1,3 @@
+[settings]
+multi_line_output=4
+known_first_party=trytond
diff --git a/modules/sale_secondary_unit/CHANGELOG b/modules/sale_secondary_unit/CHANGELOG
new file mode 100644
index 0000000000..84a1234c2f
--- /dev/null
+++ b/modules/sale_secondary_unit/CHANGELOG
@@ -0,0 +1,24 @@
+Version 6.6.0 - 2022-10-31
+--------------------------
+* Bug fixes (see mercurial logs for details)
+
+Version 6.4.0 - 2022-05-02
+* Bug fixes (see mercurial logs for details)
+* Add support for Python 3.10
+* Remove support for Python 3.6
+
+Version 6.2.0 - 2021-11-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)
+
+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..80fddcf697
--- /dev/null
+++ b/modules/sale_secondary_unit/COPYRIGHT
@@ -0,0 +1,15 @@
+Copyright (C) 2019-2022 Cédric Krier
+Copyright (C) 2019-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